EN
React - scroll stop event
4
points
In this short article, we would like to show how to detect scroll stop event ('scroll end event').
The solution for the problem is to use some trick: do some logic when scroll event doesn't occur few milliseconds after appeared.
Note: to make element scrollable we should use one of the
overflow
style property (e.g.overflowY: 'scroll'
).
Runnable example:
// ONLINE-RUNNER:browser;
// Note: uncomment import lines in your project.
// import React from 'react';
// import ReactDOM from 'react-dom';
const createScrollStopListener = (element, callback, timeout) => {
let removed = false;
let handle = null;
const onScroll = () => {
if (handle) {
clearTimeout(handle);
}
handle = setTimeout(callback, timeout || 200); // default 200 ms
};
element.addEventListener('scroll', onScroll);
return () => {
if (removed) {
return;
}
removed = true;
if (handle) {
clearTimeout(handle);
}
element.removeEventListener('scroll', onScroll);
};
};
const useScrollStopListener = (callback, timeout) => {
const containerRef = React.useRef();
const callbackRef = React.useRef();
callbackRef.current = callback;
React.useEffect(() => {
const destroyListener = createScrollStopListener(containerRef.current, () => {
if (callbackRef.current) {
callbackRef.current();
}
});
return () => destroyListener();
}, [containerRef.current]);
return containerRef;
};
// Usage example
const App = () => {
const containerRef = useScrollStopListener(() => {
console.log('onscrollstop');
});
return (
<div ref={containerRef} style={{ height: '200px', overflowY: 'scroll' }}>
<div style={{ height: '700px', background: 'silver' }}>
Scroll me up, down, up down and stop!
</div>
</div>
);
};
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
Window scroll stop event example
We are able to indicate window
as scrolled element
.
// ONLINE-RUNNER:browser;
// Note: uncomment import lines in your project.
// import React from 'react';
// import ReactDOM from 'react-dom';
const createScrollStopListener = (element, callback, timeout) => {
let removed = false;
let handle = null;
const onScroll = () => {
if (handle) {
clearTimeout(handle);
}
handle = setTimeout(callback, timeout || 200); // default 200 ms
};
element.addEventListener('scroll', onScroll);
return () => {
if (removed) {
return;
}
removed = true;
if (handle) {
clearTimeout(handle);
}
element.removeEventListener('scroll', onScroll);
};
};
const useScrollStopListener = (element, callback, timeout) => {
const callbackRef = React.useRef();
callbackRef.current = callback;
React.useEffect(() => {
const destroyListener = createScrollStopListener(element, () => {
if (callbackRef.current) {
callbackRef.current();
}
});
return () => destroyListener();
}, [element]);
};
// Usage example
const App = () => {
useScrollStopListener(window, () => {
console.log('onscrollstop');
});
return (
<div style={{ height: '1000px', background: 'silver' }}>
Scroll me up, down, up down and stop!
</div>
);
};
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);