1

I have a header that I want to hide on scroll down and show on scroll up.
To do that, I saved the scrolling position as prevScrollPos in the state to compare it to the current scrolling position onscroll, and then update prevScrollPos to the current:

 const [visible, setVisible] = React.useState(true);
 const [prevScrollPos, setPrevScrollPos] = React.useState(window.pageYOffset);

  const handleScroll = () => {
    const scrollPos = window.pageYOffset;
    const visible = scrollPos < prevScrollPos;

    setVisible(visible);
    setPrevScrollPos(scrollPos);
  }

The problem is that, for some reason PrevScrollPos doesn't get updated.
Pen: https://codepen.io/moaaz_bs/pen/jgGRoj?editors=0110

Moaaz Bhnas
  • 1,010
  • 7
  • 18
  • 36

2 Answers2

3

You need to modify your useEffect function:

  React.useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  });

Basically you don't have access to prevScrollPos in your handler, therefore prevScrollPos inside the listener will always return 0. To solve this, the dependency array should not be present.

-> + Do not forget to remove the event listener after adding it. :-)

grenzbotin
  • 2,489
  • 1
  • 12
  • 14
  • Thank you so much! It worked. Do I need to remove the event listener event if the component will never unmount? – Moaaz Bhnas Aug 04 '19 at 08:52
  • 1
    Now, you need to remove it since the event listener gets added with each render. And we need to have it because we want to be aware of the current prevScrollPos - otherwise we won't (as you saw). But in general, I would always make sure to remove the event listeners anyway, yes. – grenzbotin Aug 04 '19 at 09:06
  • Thank you for the explanation. I get it now – Moaaz Bhnas Aug 04 '19 at 09:50
0

Can you try this:

 const [visible, setVisible] = React.useState(true);
 const [prevScrollPos, setPrevScrollPos] = React.useState(window.pageYOffset);

  const handleScroll = () => {
    const scrollPos = window.pageYOffset;
    const visible_new = scrollPos < prevScrollPos;

    setVisible(visible_new);
    setPrevScrollPos(scrollPos);
  }
  • I thought that the problem concerned the visible variable which represents the state and which it seems to me is not correctly modified here: const visible = scrollPos – Merci Dieu KIMPOLO Aug 04 '19 at 08:37