`useScrolling` doesn't clean up its timer
Author: stevebaxterCreated Oct 19, 2025Updated Feb 19, 2026
What is the current behavior?
useScrolling can leave a timer running on unmount because it doesn't clean up correctly.
I think we need to update the code to something like:
const useScrolling = (ref: RefObject<HTMLElement>): boolean => {
const [scrolling, setScrolling] = useState<boolean>(false);
useEffect(() => {
if (ref.current) {
let scrollingTimeout: ReturnType<typeof setTimeout>;
const handleScrollEnd = () => {
setScrolling(false);
};
const handleScroll = () => {
setScrolling(true);
clearTimeout(scrollingTimeout);
scrollingTimeout = setTimeout(() => handleScrollEnd(), 150);
};
on(ref.current, "scroll", handleScroll, false);
return () => {
// This is the change from the original implementation
clearTimeout(scrollingTimeout);
if (ref.current) {
off(ref.current, "scroll", handleScroll, false);
}
};
}
return () => {};
}, [ref]);
return scrolling;
}We need to call clearTimeout() in the cleanup function to correctly remove the timeout.
Steps to reproduce it and if possible a minimal demo of the problem: This turned up intermittently in our Jest tests.
What is the expected behavior? The timeout should be cleaned up.
A little about versions:
- OS: macOS 26
- Browser (vendor and version): Node 22.12 (in tests)
- React: 17.0.2
react-use: 17.3.1- Did this worked in the previous package version? No, it looks like the same issue is present in master.
Source: streamich/react-use