Skip to content

Instantly share code, notes, and snippets.

@tilap
Last active April 10, 2024 06:44
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tilap/743560bee45c89622f360b6544260905 to your computer and use it in GitHub Desktop.
Save tilap/743560bee45c89622f360b6544260905 to your computer and use it in GitHub Desktop.
React hook to get scroll position
import { useCallback, useLayoutEffect, useRef } from 'react';
const isBrowser = typeof window !== 'undefined';
const getScrollPosition = ({ element, useWindow }) => {
if (!isBrowser) return { x: 0, y: 0 };
if (useWindow) {
return { x: window.scrollX, y: window.scrollY };
}
const target = element ? element.current : document.body;
const position = target.getBoundingClientRect();
return { x: position.left, y: position.top };
};
const useScrollPosition = ({ handler, deps, element, useWindow, debounce }) => {
const position = useRef(getScrollPosition({ useWindow }));
const throttleTimeout = useRef(null);
const callBack = useCallback(() => {
const currPos = getScrollPosition({ element, useWindow });
if (handler) {
handler({ previous: position.current, current: currPos });
}
position.current = currPos;
throttleTimeout.current = null;
}, [handler, element, useWindow]);
useLayoutEffect(() => {
const handleScroll = () => {
if (debounce) {
if (throttleTimeout.current === null) {
throttleTimeout.current = setTimeout(callBack, debounce);
}
} else {
callBack();
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [callBack, deps, debounce]);
if (!handler) {
return position.current;
}
};
export default useScrollPosition;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment