useDocumentScroll
- Published on
This hook is used to execute a callback code when the user scrolls.
useDocumentScroll.tsx
import { useEffect, useState } from 'react';
import { throttle } from 'lodash';
export function useDocumentScroll(
callback: (params: { previousScrollTop: number; currentScrollTop: number }) => void
) {
const [, setScrollPosition] = useState(0);
let previousScrollTop = 0;
function handleDocumentScroll() {
const { scrollTop: currentScrollTop } = document.documentElement || document.body;
setScrollPosition((previousPosition) => {
previousScrollTop = previousPosition;
return currentScrollTop;
});
callback({ previousScrollTop, currentScrollTop });
}
const handleDocumentScrollThrottled = throttle(handleDocumentScroll, 250);
useEffect(() => {
window.addEventListener('scroll', handleDocumentScrollThrottled);
return () => window.removeEventListener('scroll', handleDocumentScrollThrottled);
}, []);
}
This is how you use the hook in a component to show or hide navbar (like on this site).
navbar.tsx
let timer: any;
const [shouldHideHeader, setShouldHideHeader] = useState(false);
const MINIMUM_SCROLL = 80;
const TIMEOUT_DELAY = 200;
useDocumentScroll((callbackData) => {
const { previousScrollTop, currentScrollTop } = callbackData;
const isScrolledDown = previousScrollTop < currentScrollTop;
const isMinimumScrolled = currentScrollTop > MINIMUM_SCROLL;
timer = setTimeout(() => {
setShouldHideHeader(isScrolledDown && isMinimumScrolled);
}, TIMEOUT_DELAY);
});
useEffect(() => () => clearTimeout(timer));
return (
<>
// your html code here. You can use shouldHideHeader variable
</>
);