UNPKG

@mirawision/reactive-hooks

Version:

A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.

75 lines (74 loc) 2.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useInfiniteScroll = useInfiniteScroll; const react_1 = require("react"); /** * A hook that implements infinite scrolling using Intersection Observer. * Triggers loadMore when the target element becomes visible. * * @param opts Configuration options * @returns Object with ref callback, loading state, and error state * * @example * const { ref, loading } = useInfiniteScroll({ * hasMore: true, * loadMore: () => fetchNextPage(), * }); * * return ( * <div> * {items.map(item => <Item key={item.id} {...item} />)} * <div ref={ref}>{loading ? 'Loading...' : null}</div> * </div> * ); */ function useInfiniteScroll(opts) { const [loading, setLoading] = (0, react_1.useState)(false); const [error, setError] = (0, react_1.useState)(null); // Refs for cleanup and state tracking const observerRef = (0, react_1.useRef)(); const loadingRef = (0, react_1.useRef)(loading); loadingRef.current = loading; // Cleanup function const cleanup = (0, react_1.useCallback)(() => { if (observerRef.current) { observerRef.current.disconnect(); observerRef.current = undefined; } }, []); // Load more function with loading state const handleLoadMore = (0, react_1.useCallback)(async () => { if (loadingRef.current || !opts.hasMore) return; try { setLoading(true); setError(null); await opts.loadMore(); } catch (err) { setError(err); } finally { setLoading(false); } }, [opts.hasMore, opts.loadMore]); // Ref callback to observe element const ref = (0, react_1.useCallback)((element) => { cleanup(); if (!element || !opts.hasMore) return; // Create new observer const observer = new IntersectionObserver((entries) => { const [entry] = entries; if (entry.isIntersecting) { handleLoadMore(); } }, { rootMargin: opts.rootMargin ?? '50px', threshold: opts.threshold ?? 0, }); observer.observe(element); observerRef.current = observer; }, [opts.hasMore, opts.rootMargin, opts.threshold, handleLoadMore, cleanup]); return { ref, loading, error }; }