/** * Saves a feed page's state, with its scroll position, as the page is left. * * @module */ import { useEffect, useLayoutEffect, useRef } from "react"; /** * Calls `onSave(scrollY)` when the component unmounts or the tab is hidden * (`pagehide`), while `enabled`. Feed pages pass `enabled` once their feed is * loaded, and an `onSave` that calls `useFeedCache`'s `saveState`. * * It doesn't save on scroll, since serializing the whole feed there took a long * task at every pause. */ export function useScrollSave( enabled: boolean, onSave: (scrollY: number) => void, ): void { // A ref, so a new `onSave` on every render doesn't re-attach the listeners. const onSaveRef = useRef(onSave); useLayoutEffect(() => { onSaveRef.current = onSave; }); useEffect(() => { if (!enabled) return; // Tracked on scroll: by the time the unmount runs, the next page may have // scrolled the window back to the top. let y = globalThis.scrollY; const onScroll = () => { y = globalThis.scrollY; }; const save = () => onSaveRef.current(y); globalThis.addEventListener("scroll", onScroll, { passive: true }); globalThis.addEventListener("pagehide", save); return () => { globalThis.removeEventListener("scroll", onScroll); globalThis.removeEventListener("pagehide", save); save(); }; }, [enabled]); }