skip to Main Content

I have a list of refs that is being forwarded to the child components. They seem to work fine as I can do operations with them as feedback to the user actions (in this case, it is scrolling into view). However, I want to scroll to them when component is rendered/mounted, which sounds like a classic ref usage: add ref dependencies to a useEffect and scroll when they are ready. But it basically does not work. When I console.log out the refs, I see the ref.current is assigned. However when I console.log refs[scrollTo], it is undefined. This might be related to how chrome browser consoles work though.

So here is my example code:

const MyComponent = (props) => {
  const refs = {
    a: useRef<HTMLDivElement>(null),
    b: useRef<HTMLDivElement>(null),
    c: useRef<HTMLDivElement>(null),
  }
  
  useEffect(() => {
    if (props.scrollTo && refs[props.scrollTo].current) {
      refs[props.scrollTo].current.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }, [refs.a.current, refs.b.current, refs.c.current]);

  return <>
    <ChildComponent key='a' ref={refs.a} onClick={
      refs.a.current?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    } />
    <ChildComponent key='b' ref={refs.b} onClick={
      refs.b.current?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    } />
    <ChildComponent key='c' ref={refs.c} onClick={
      refs.c.current?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    } />
  </>
};

refs[props.scrollTo].current always returns null here in the use effect, preventing me to scroll there on load. useCallback solution also does not apply here for me as well, since I need those DOM refs for scrollintoview behaviour on onclicks. What am I missing here? And how can I ensure the behaviour I want?

2

Answers


  1. Incorrect Dependencies: Including references (refs.a.current, refs.b.current, etc.) in the dependencies of useEffect can lead to unexpected behaviors. refs.a.current does not change frequently, so React may not properly detect changes in the references.

    Login or Signup to reply.
  2. props.scrollTo needs to be a string that contains one of "a", "b", or "c".

    Also, if it is initialised as something else (possibly null in your case), with its value being set in an effect, then you need to add props.scrollTo to your dependency array.

    useEffect(() => {
        if (props.scrollTo && refs[props.scrollTo].current) {
            refs[props.scrollTo].current.scrollIntoView({ behavior: 'smooth', block: 'start' });
        },
    }, [refs.a.current, refs.b.current, refs.c.current, props.scrollTo]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search