How to change className in scroll EventListener in react?
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!