How to change className in scroll EventListener in react?

Reza Samkhanian
2 min readFeb 8, 2021
Photo by Robert Katzki on Unsplash

One of my recent tasks was to add shadow to sticky div when div sticks on top of the screen. As I was trying to do this I faced different issues that I like to share with you.

EventListener

Probably the first thing that came to your mind after knowing what we’re trying to do was using state and scroll eventListener so let’s give it a try.
Before jumping to code let me remind you of some points:
1. Be careful where you attach eventListner to document or any other element. Using it inside the component function will attach a listener on every render and you gonna feel something beyond IE capabilities
2. Don’t forget to use removeEventLisetner in cleanup function and don’t pass an anonymous function since it won’t be removed.

It’s straightforward. When the component mounts checkScroll is attached to scroll I get bar with document.getElementById since bar topOffset may not be fixed. You can use ref too. Then we check if window.scrollY is bigger than bar.offsetTop . I also added a color change to make it more obvious. Everything seems to work just right(or is it?).
If you open the console you can see shadow value is not the same as what you see. The issue as you can see in react docs is :

Any function inside a component, including event handlers and effects, “sees” the props and state from the render it was created in.

In this case, using state works fine but keep this in mind and use other workarounds if you had to.
It seems this story ends here But …

Android chrome

I was testing and shadow was smooth on Desktop and IOS but in android devices, it was flickering. Did setShadow(true) cause rerender!!? I was dubious about it and I was right (setting the same value in state hooks unlike setState will not render). from “You don’t know JS” I knew Js might work differently in different environments so I inspected an android device with chrome (how?) and I noticed shadow is switching between true and false! I used console.log to see scrollY and offsetTop and the result was the answer. scrollY in an android device is not an integer and has a fraction more or less than offsetTop. To fix this I added 10 to scrollY . Math.floor or Math.round because scrollY sometimes is lesser would not work. you may use other solutions but you know the main point.

That was it. It wasn’t a long story but scrollY in android devices was a little bit tricky and I did not use state in eventListener before. if you have questions or other ways to do this, I’ll be happy to know!

--

--