import { useCallback, useEffect, useState } from "react"; /** * Observe a sentinel element and call `onLoadMore` when it scrolls into view. * * The sentinel is tracked via a state-backed callback ref rather than a plain * `useRef` so the observer re-attaches whenever the underlying DOM node * changes — e.g. when the index page swaps the active feed tab and a fresh * sentinel `
` mounts in place of the old one. A static ref would keep * observing the now-detached node and silently stop loading more. */ export function useInfiniteScroll(onLoadMore: () => void, enabled: boolean) { const [sentinel, setSentinel] = useState(null); const handleIntersect = useCallback( (entries: IntersectionObserverEntry[]) => { if (entries[0].isIntersecting && enabled) { onLoadMore(); } }, [onLoadMore, enabled], ); useEffect(() => { if (!sentinel) return; const observer = new IntersectionObserver(handleIntersect, { rootMargin: "200px", }); observer.observe(sentinel); return () => observer.disconnect(); }, [handleIntersect, sentinel]); return setSentinel; }