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

3
  • I tested it on your pen. It works correctly Commented Aug 4, 2019 at 8:13
  • @TienDuong Check the console Commented Aug 4, 2019 at 8:16
  • 2
    When you add the scroll handler then handle scroll function is bind to the first prevScrollPos value. See this answer to solve your problem stackoverflow.com/questions/55265255/… Commented Aug 4, 2019 at 8:17

2 Answers 2

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. :-)

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much! It worked. Do I need to remove the event listener event if the component will never unmount?
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.
Thank you for the explanation. I get it now
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); } 

1 Comment

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 <prevScrollPos; it's better to use another variable at this level

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.