5

I'd like to scroll to a given horizontal position in an element immediately after it's rendered by React. For context, I'm using Next.js with server-side rendering, so useLayoutEffect isn't an option.

export default function WideElement () {
  const ref = useRef(null)

  useEffect(function () {
    ref.current.scrollLeft = 1000
  }, [])

  return (
    <Container ref={ref}>
      ...
    </Container>
  )
}

However, the above code doesn't scroll when the page loads. Here the ... represents a long list of child elements that stack horizontally and overflow the container.

I have noticed that if I impose an artificial delay on the scroll, it seems to work fine, and Container is immediately scrolled 1000 pixels to the left.

export default function WideElement () {
  const ref = useRef(null)

  useEffect(function () {
    setTimeout(function() {
      ref.current.scrollLeft = 1000
    }, 1000)
  }, [])

  return (
    <Container ref={ref}>
      ...
    </Container>
  )
}

I think I might be misunderstanding useEffect. What am I missing, and how could I make this work?

Kieran
  • 2,554
  • 3
  • 26
  • 38
  • I tried your code in sandbox. https://codesandbox.io/s/objective-visvesvaraya-zngjp . Its working fine without setTimeout. check here. – Kais Jan 14 '20 at 04:59
  • 2020 and same issue here. Works with the timeout. – Joan Feb 18 '20 at 06:16

1 Answers1

1

if you require that the ref be available to do something when it mounts, you can use a callback method passed to the ref attribute instead of relying on a timeout. The callback method accepts the node as a parameter, and you can do with it what you will from there.

It also gives you opportunity to react to any ref changes, or mounting/unmounting

This should be more reliable than a timeout.

export default function WideElement () {
  const ref = useRef(null);

  const setRef = useCallback((node) => {
     if (node) {
         node.scrollLeft = 1000;  
     }
     ref.current = node;               
  },[]) 

  return (
    <Container ref={setRef}>
      ...
    </Container>
  )
}
GBourke
  • 1,834
  • 1
  • 7
  • 14