# useInfiniteScroll > Triggers loading near the scroll end. - Category: DOM - Package: `hookli` (install with `npm i hookli`) - Docs: https://hookli.vercel.app/docs/use-infinite-scroll ## Signature ```ts useInfiniteScroll(fetchMoreData: () => Promise): boolean ``` ## Parameters - `fetchMoreData`: `() => Promise` — Called when the window scroll comes within 500px of the document bottom. Must return a promise — the hook stays in the fetching state until it resolves. ## Returns - `isFetching`: `boolean` — True while a triggered fetchMoreData promise is pending; blocks re-triggering until it resolves. ## Usage ```tsx import { useCallback, useState } from "react"; import { useInfiniteScroll } from "hookli"; const page = (start: number) => Array.from({ length: 10 }, (_, i) => `Item ${start + i + 1}`); export function Demo() { const [items, setItems] = useState(() => page(0)); const fetchMoreData = useCallback( () => new Promise((resolve) => { setItems((prev) => [...prev, ...page(prev.length)]); resolve(); }), [], ); const isFetching = useInfiniteScroll(fetchMoreData); return (
    {items.map((item) => (
  • {item}
  • ))}
{isFetching &&

Loading more…

}
); } ``` ## Source `src/hooks/useInfiniteScroll.hook.ts` ```ts import { useEffect, useState } from "react"; type FetchMoreData = () => Promise; export const useInfiniteScroll = (fetchMoreData: FetchMoreData): boolean => { const [isFetching, setIsFetching] = useState(false); useEffect(() => { const handleScroll = () => { const isNearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 500; if (isNearBottom && !isFetching) { setIsFetching(true); fetchMoreData().then(() => setIsFetching(false)); } }; window.addEventListener("scroll", handleScroll); return () => { window.removeEventListener("scroll", handleScroll); }; }, [fetchMoreData, isFetching]); return isFetching; }; ```