2

I am using the useEffect hook below to sense the page scroll but it is not logging "yes" to the console. What am I missing? My page is scrolling more than 50px so it should print out "yes".

useEffect(() => {

        const scrollFun = window.addEventListener("scroll", () => {
            if(window.pageYOffset%50 === 0) {
                console.log("yes");
            }
        });

        return () => {
            window.removeEventListener("scroll", scrollFun);
        };        

    }, []);
3
  • 1
    Copy/pasted your code into a codesandbox and it appears to be logging as expected. Note though, window.addEventListener is a void return so you aren't removing the callback on component unmount. Commented May 5, 2021 at 4:46
  • Do you want to log when the page has scrolled by 50px, or are you trying to log every 50px of scrolling? Commented May 5, 2021 at 5:13
  • That is exactly my problem too. You code works in the demo box but not when I add it to my app. Still stuck on why it doesn't work for my app. Commented May 6, 2021 at 1:29

2 Answers 2

2

It's still a bit unclear if you want just a single "page has scrolled 50px" or if you are looking for continual monitoring of scrolling every 50px so I'll try to answer both and you can choose which ever is closer.

Scenario 1 - Scroll first 50px and log

This one is trivial. I suggest using a React ref to "capture" having scrolled the page by at least 50px, resetting when scrolled back.

const scrolled50Ref = useRef();

useEffect(() => {
  const scrollFun = () => {
    if (window.pageYOffset > 50) {
      if (!scrolled50Ref.current) {
        scrolled50Ref.current = true;
        console.log('scrolled 50 px');
      }
    } else {
      scrolled50Ref.current = false;
    }
  }
  
  window.addEventListener("scroll", scrollFun);

  return () => {
    window.removeEventListener("scroll", scrollFun);
  };
}, []);

Scenario 2 - Log every 50px of scrolling

This one isn't as trivial and likely what you are seeing. The issue here is that many browsers use accelerated scrolling, so you won't hit every pageYOffset value. In other words, after scrolling a certain speed/velocity you are likely not to hit an pageYOffset evenly divisible by 50.

The "fix" here is to increase the "window" of divisible by 50.

useEffect(() => {
  const scrollFun = () => {
    if (window.pageYOffset % 50 >= 45) {
      console.log("scrolled 50-ish pixels");
    }
  }
  
  window.addEventListener("scroll", scrollFun);

  return () => {
    window.removeEventListener("scroll", scrollFun);
  };
}, []);

Demo

Edit adding-an-event-listener-with-useeffect-hook-for-scrolling (forked)

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

5 Comments

Thanks for the response. My final goal is to make an element scrollable then fixed when it's offset from the top of page at a given distance. But before that I wanted to play with how the useEffect is used to sense the scrolling and log that to the console which is why I tried logging every 50 pixels. For that purpose scenario 2 is acceptable. But the code you have there still is not logging anything for me. It works in the demo box here but not when I use it in my app. Do you know what the reason could be?
@Dag Dunno, seems odd. What happens if you click drag the scroll thumb slowly? Do you see logs when you expect them? Can you add a console.log(window.pageScrollY) in the callback to see how the offset progresses?
I did that and still no log. I am thinking the event listener is not activated to begin with. I don't know why though.
@Dag Have you tried running your app in other browsers? Does issue still reproduce in them? Can you create a project in github that reproduces the issue that we can clone and run locally?
It works now. I am not completely sure what made it work but it did after I made a bunch of changes to my css formatting. I suspect it may have to do with the type of position for some of the elements in the page. Anyway thanks for the feedback!
0

Change your if condition with this one:

  if (window.pageYOffset > 0)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.