1

i'm using useRef for addEventListener but doesn't work, is something wrong here?

parent component:

const parent = () => {
  const el = useRef()
  const element = el.current && el.current 

  useEffect(() => {
    if (element) {
      const scrollHandler = e => {
        console.log(e);
      };

      element.addEventListener("scroll", scrollHandler);

      return () => {
        element.removeEventListener("scroll", scrollHandler);
      };
    }
  }, [element]);

  return (
    <Child ref={el} />
  )
}

child component:

const child = React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>something...</div>
  )
})
  • For `scroll` event to work, content of the `Child` component needs to have enough height for the webpage to be scrollable. Try setting `200vh` height on the `div` element in `Child` component. Then you will see the `scroll` event working as it should. – Yousaf Dec 26 '20 at 11:42
  • Useref doesn't trigger rerender, and bound ref object before useEffect. Just use el.current without element. – Cenk Çetinkaya Dec 26 '20 at 11:42
  • https://stackoverflow.com/users/6094348/yousaf Yeah you are right, i have enough scroll for element, but still doesn't work – mohammad nowresideh Dec 26 '20 at 11:48
  • https://stackoverflow.com/users/6165701/cenk-%c3%87etinkaya I did it as you said, but still doesn't work. – mohammad nowresideh Dec 26 '20 at 11:50
  • https://stackoverflow.com/users/6094348/yousaf Thank you so much for helping me, but i want `element.addEventListener` not `window.addEventListener` i wrote wrong dude. may you check again? – mohammad nowresideh Dec 26 '20 at 12:02
  • 1
    Here's [the working demo](https://codesandbox.io/s/async-wind-s4hyf?fontsize=14&hidenavigation=1&theme=dark). For `scroll` event to work on an element, that element should be scrollable and you need to use `el.current` instead of `element` inside the `useEffect` hook. – Yousaf Dec 26 '20 at 12:11
  • https://stackoverflow.com/users/6094348/yousaf Thanks man. – mohammad nowresideh Dec 26 '20 at 12:22

1 Answers1

0

Based on React Hook Flow the useEffect will be called after the child is being rendered and the refs are set, so you should be able to empty the useEffect dependency and still having a ref that's being set. [![enter image description here][1]][1]

Check this comment from Dan as well which might be helpful for clarification of what's happening: https://github.com/facebook/react/issues/14387#issuecomment-503616820

also created this codesandbox that you can play with code to see what I'm talking about: https://codesandbox.io/p/sandbox/elastic-cache-jgv7xw change your parent component to this to avoid getting stale state:


const parent = () => {
  const el = useRef();

  useEffect(() => {
    if (el.current) {
      const scrollHandler = (e) => {
        console.log(e);
      };

      el.current.addEventListener("scroll", scrollHandler);

      return () => {
        el.current.removeEventListener("scroll", scrollHandler);
      };
    }
  }, []);

  return <Child ref={el} />;
};


  [1]: https://i.stack.imgur.com/YxEQ4.jpg
Taghi Khavari
  • 6,272
  • 3
  • 15
  • 32