0

I understand React recommends to add and remove event listeners every time when App is updated, however, I realized below code works even though the event listener was removed (at least in my understandings):

function App() {

  const [posY, setPosY] = useState(0);

  useEffect(() => {
    const handleScroll = (e) => window.requestAnimationFrame(()=>{
      setPosY(window.pageYOffset);
    });

    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  return <div>{posY}</div>;
}

Can anyone help me understand why it still listens to scroll events? I thought it won't work because:

  • The event listener was removed by this line, return () => window.removeEventListener("scroll", handleScroll);
  • The useEffect hook runs only once at the very beginning due to the blank array
  • setPosY(window.pageYOffset) invoke a new update/render, and the next App() update will skip useEffect.

Are above three statements correct? It seems that I don't fully understand what is going on here.

cypark
  • 838
  • 6
  • 21
  • 2
    The `return` of a `useEffect` runs when the component is unmounted, not once it is run. – Shmili Breuer May 26 '21 at 20:55
  • @ShmiliBreuer Ohhh I got you. Thank you for your input! I have one more question then. If the `App()` is the very base component that never unmounts until the app is closed by the user, can I deal with the scroll event as above? If not recommended, is it because it's an anti-pattern or is there any potential issue doing so? – cypark May 26 '21 at 21:04
  • I can not say about `anti-pattern` as I don't know, however I recently had an issue when doing so in a website I developed and needed to know the overall page scroll position to set the background color of the header, the issue was that this causes the whole app to re-render on each scroll and besides being heavy it caused a `useEffect` (calling an API) in a child component to be called on each re-render )-:, so I moved the event listener to the header component and although it also stays on the page all the time it is a smaller and less complex component so it is not that heavy to re-render. – Shmili Breuer May 26 '21 at 21:18
  • @ShmiliBreuer Thanks for your input. For anyone who needs more detail, please refer to [this answer](https://stackoverflow.com/a/65225493/2373800) and [this one](https://stackoverflow.com/a/59841947/2373800). – cypark May 26 '21 at 21:52

0 Answers0