Code Snippets
/

React useInfiniteScroll Hook

React useInfiniteScroll Hook

Infinite scroll feels simple until you wire IntersectionObserver, page tracking, and the request lifecycle together. This snippet covers a sentinel-ref hook that fires a load callback when the bottom marker scrolls into view, a paginated variant that tracks the page state for you, and an end-of-feed guard that stops calling the callback once the server says there is no more data.

JavaScript
Hard
react
hooks
code-template
performance-optimization

354 views

1

function useInfiniteScroll(onLoad, options = {}) {
    const sentinelRef = useRef(null);
    const cbRef = useRef(onLoad);
    useEffect(() => { cbRef.current = onLoad; }, [onLoad]);
    useEffect(() => {
        if (typeof IntersectionObserver === 'undefined') return undefined;
        const node = sentinelRef.current;
        if (!node) return undefined;
        const observer = new IntersectionObserver((entries) => {
            for (const entry of entries) {
                if (entry.isIntersecting) cbRef.current();
            }
        }, { rootMargin: options.rootMargin || '200px', threshold: options.threshold || 0 });
        observer.observe(node);
        return () => observer.disconnect();
    }, [options.rootMargin, options.threshold]);
    return sentinelRef;
}

function useRef(v) { return { current: v }; }
function useEffect(fn) { fn(); }
const sentinel = useInfiniteScroll(() => console.log('load more'));
console.log('sentinel ref:', sentinel.current);

The hook hands back a ref for the consumer to attach to a sentinel element near the end of the list. An IntersectionObserver watches that node, and when it crosses the viewport (with a 200px head start so loading begins before the user hits bottom), the callback fires. Storing the callback in a ref keeps the observer stable across renders so it does not detach and reattach when parent state changes. This is conceptually simpler than scroll-event math and works correctly even when the list is inside a scrollable container.

2 more snippets in this entry are available for premium members.

Upgrade to Premium