quick and dirty implementation
import { useRef, useEffect, useCallback } from "react";
import throttle from "lodash/throttle";
const windowScrollPositionKey = {
y: "pageYOffset",
x: "pageXOffset"
};
const documentScrollPositionKey = {
y: "scrollTop",
x: "scrollLeft"
};
const getScrollPosition = (axis, element) =>
element?.[documentScrollPositionKey[axis]] ||
window[windowScrollPositionKey[axis]] ||
document.documentElement[documentScrollPositionKey[axis]] ||
document.body[documentScrollPositionKey[axis]] ||
0;
export const ReactWindowScroller = ({
children,
throttleTime = 10,
isGrid = false,
element = undefined
}) => {
const ref = useRef();
const outerRef = useRef();
useEffect(() => {
const handleWindowScroll = throttle(() => {
const { offsetTop = 0, offsetLeft = 0 } = outerRef.current || {};
const scrollTop = getScrollPosition("y", element) - offsetTop;
const scrollLeft = getScrollPosition("x", element) - offsetLeft;
if (isGrid) ref.current?.scrollTo({ scrollLeft, scrollTop });
if (!isGrid) ref.current?.scrollTo(scrollTop);
}, throttleTime);
(element ?? window).addEventListener("scroll", handleWindowScroll);
return () => {
handleWindowScroll.cancel();
(element ?? window).removeEventListener("scroll", handleWindowScroll);
};
}, [isGrid]);
const onScroll = useCallback(
({ scrollLeft, scrollTop, scrollOffset, scrollUpdateWasRequested }) => {
if (!scrollUpdateWasRequested) return;
const top = getScrollPosition("y", element);
const left = getScrollPosition("x", element);
const { offsetTop = 0, offsetLeft = 0 } = outerRef.current || {};
scrollOffset += Math.min(top, offsetTop);
scrollTop += Math.min(top, offsetTop);
scrollLeft += Math.min(left, offsetLeft);
if (!isGrid && scrollOffset !== top) (element ?? window).scrollTo(0, scrollOffset);
if (isGrid && (scrollTop !== top || scrollLeft !== left)) {
(element ?? window).scrollTo(scrollLeft, scrollTop);
}
},
[isGrid]
);
return children({
ref,
outerRef,
style: {
width: isGrid ? "auto" : "100%",
height: "100%",
display: "inline-block"
},
onScroll
});
};
quick and dirty implementation