Reputation: 85
Here is my code
const [isScrollLocked, setIsScrollLocked] = useState(false)
const handleScroll = (section, scrollLocked) => {
if (!scrollLocked) {
document.getElementById(section).scrollIntoView()
document.querySelector('body').classList.add('overflow-hidden')
setIsScrollLocked(true)
setTimeout(() => {
document.querySelector('body').classList.remove('overflow-hidden')
setIsScrollLocked(false)
}, 1500)
}
}
useEffect(() => {
const handler = (e) => handleScroll(nextSection, isScrollLocked)
document.addEventListener('scroll', handler)
// cleanup callback, that will be called before the effect runs again
return () => document.removeEventListener('scroll', handler)
}, [nextSection, isScrollLocked])
It seems that the callback cleanup that runs after the useEffect is making it so that the scrollIntoView inside handleScroll never takes place. However if I console.log before or after it fires off. If I remove the callback the scrollIntoView works as normal but I am stacking up thousands of scroll events and crashing my application.
If anybody could spot why the callback cleanup is having this effect and explain it to me I would really like to know.
Upvotes: 0
Views: 493
Reputation: 4214
The problem is how your setTimeout
and useEffect
are interacting. Your useEffect
is running everytime isScrollLocked
changes. Since your setTimeout
is changing isScrollLocked
, it makes it look like useEffect
is running 1.5 seconds later.
Try removing the isScrollLocked
watcher:
const [isScrollLocked, setIsScrollLocked] = useState(false);
const handleScroll = (section) => {
if (!isScrollLocked) {
document.getElementById(section).scrollIntoView();
document.querySelector("body").classList.add("overflow-hidden");
setIsScrollLocked(true);
setTimeout(() => {
document.querySelector("body").classList.remove("overflow-hidden");
setIsScrollLocked(false);
}, 1500);
}
};
useEffect(() => {
const handler = (e) => handleScroll(nextSection);
document.addEventListener("scroll", handler);
// cleanup callback, that will be called before the effect runs again
return () => document.removeEventListener("scroll", handler);
});
Here's a link: https://codesandbox.io/s/react-hooks-counter-demo-forked-7n064
Upvotes: 1