ahooks
Version:
react hooks library
51 lines (50 loc) • 2.14 kB
JavaScript
import useRafState from '../useRafState';
import useLatest from '../useLatest';
import { getTargetElement } from '../utils/domTarget';
import useEffectWithTarget from '../utils/useEffectWithTarget';
function useScroll(target, shouldUpdate = () => true) {
const [position, setPosition] = useRafState();
const shouldUpdateRef = useLatest(shouldUpdate);
useEffectWithTarget(() => {
const el = getTargetElement(target, document);
if (!el) {
return;
}
const updatePosition = () => {
let newPosition;
if (el === document) {
if (document.scrollingElement) {
newPosition = {
left: document.scrollingElement.scrollLeft,
top: document.scrollingElement.scrollTop,
};
}
else {
// When in quirks mode, the scrollingElement attribute returns the HTML body element if it exists and is potentially scrollable, otherwise it returns null.
// https://developer.mozilla.org/zh-CN/docs/Web/API/Document/scrollingElement
// https://stackoverflow.com/questions/28633221/document-body-scrolltop-firefox-returns-0-only-js
newPosition = {
left: Math.max(window.pageXOffset, document.documentElement.scrollLeft, document.body.scrollLeft),
top: Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop),
};
}
}
else {
newPosition = {
left: el.scrollLeft,
top: el.scrollTop,
};
}
if (shouldUpdateRef.current(newPosition)) {
setPosition(newPosition);
}
};
updatePosition();
el.addEventListener('scroll', updatePosition);
return () => {
el.removeEventListener('scroll', updatePosition);
};
}, [], target);
return position;
}
export default useScroll;