### Install Project Dependencies Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Run this command after cloning the repository to install all necessary project dependencies. ```bash npm install ``` -------------------------------- ### Install react-infinite-scroll-hook Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/packages/react-infinite-scroll-hook/README.md Install the package using npm. ```sh npm install react-infinite-scroll-hook ``` -------------------------------- ### Start Local Development Server Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Starts the demo Next.js app using the local version of react-infinite-scroll-hook. Access the app at http://localhost:3000. ```bash npm run dev ``` -------------------------------- ### Run Development Server Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/apps/demo/README.md Execute this command to start the development server for the Next.js project. Open http://localhost:3000 in your browser to view the application. ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` -------------------------------- ### Window-level Vertical Scroll Example Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Example demonstrating how to use the `useInfiniteScroll` hook for window-level vertical scrolling. It shows how to attach the `infiniteRef` to a sentry element and configure options like `rootMargin`. ```APIDOC ## Window-level Vertical Scroll ### Description Attach only `infiniteRef` to the sentry. The `IntersectionObserver` uses the document viewport as its root. `rootMargin` pre-triggers loading before the sentry is fully visible, reducing perceived latency. ### Usage ```tsx 'use client'; import { useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; interface Item { key: number; value: string } function useLoadItems() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { // Simulate a paginated API response const data: Item[] = Array.from({ length: 20 }, (_, i) => ({ key: items.length + i, value: `Item ${items.length + i}`, })); // Set hasNextPage to false when you have reached the last page setItems((prev) => [...prev, ...data]); setHasNextPage(items.length + data.length < 100); } catch (err) { setError(err instanceof Error ? err : new Error('Load failed')); } finally { setLoading(false); } } return { loading, items, hasNextPage, error, loadMore }; } export default function WindowScrollPage() { const { loading, items, hasNextPage, error, loadMore } = useLoadItems(); // infiniteRef → attach to the sentry element // rootRef → not needed for window scroll const [infiniteRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), // stop on error; clear error to resume rootMargin: '0px 0px 400px 0px', // trigger 400px before sentry is visible }); return (
    {items.map((item) => (
  • {item.value}
  • ))}
{error &&

Error: {error.message}

} {/* Sentry: keep mounted as long as there are more pages */} {hasNextPage && (
{loading ? 'Loading…' : null}
)}
); } ``` ``` -------------------------------- ### Basic Window Scroll Example Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/packages/react-infinite-scroll-hook/README.md Implement infinite scrolling that observes the window. The 'sentry' component (Loading) is attached to the infinite scroll hook, and its visibility triggers the 'loadMore' function. Configure 'rootMargin' to trigger loading before the sentry is fully visible. ```tsx import useInfiniteScroll from 'react-infinite-scroll-hook'; function WindowScroll() { const { loading, items, hasNextPage, error, loadMore } = useLoadItems(); const [infiniteRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, // When there is an error, we stop infinite loading. // It can be reactivated by setting "error" state as undefined. disabled: Boolean(error), // `rootMargin` is passed to `IntersectionObserver`. // We can use it to trigger 'onLoadMore' when the sentry comes near to become // visible, instead of becoming fully visible on the screen. rootMargin: '0px 0px 400px 0px', }); return (
{items.map((item) => ( {item.value} ))} {hasNextPage && }
); } ``` -------------------------------- ### Window-Level Vertical Scroll Example Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Demonstrates implementing infinite scroll for a vertical list using the hook. Attach the returned `infiniteRef` to a sentry element. `rootRef` is not needed for window-level scrolling. The `rootMargin` option is used to pre-trigger loading. ```tsx 'use client'; import { useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; interface Item { key: number; value: string } function useLoadItems() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { // Simulate a paginated API response const data: Item[] = Array.from({ length: 20 }, (_, i) => ({ key: items.length + i, value: `Item ${items.length + i}`, })); // Set hasNextPage to false when you have reached the last page setItems((prev) => [...prev, ...data]); setHasNextPage(items.length + data.length < 100); } catch (err) { setError(err instanceof Error ? err : new Error('Load failed')); } finally { setLoading(false); } } return { loading, items, hasNextPage, error, loadMore }; } export default function WindowScrollPage() { const { loading, items, hasNextPage, error, loadMore } = useLoadItems(); // infiniteRef → attach to the sentry element // rootRef → not needed for window scroll const [infiniteRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), // stop on error; clear error to resume rootMargin: '0px 0px 400px 0px', // trigger 400px before sentry is visible }); return (
    {items.map((item) => (
  • {item.value}
  • ))}
{error &&

Error: {error.message}

} {/* Sentry: keep mounted as long as there are more pages */} {hasNextPage && (
{loading ? 'Loading…' : null}
)}
); } ``` -------------------------------- ### Scrollable Container Example Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/packages/react-infinite-scroll-hook/README.md Implement infinite scrolling within a specific scrollable container. Use the 'rootRef' option to specify the container element that the hook should observe for scrolling. The 'sentry' component (Loading) is still used to trigger loading. ```tsx import useInfiniteScroll from 'react-infinite-scroll-hook'; function VerticalElementScrollPage() { const { loading, items, hasNextPage, error, loadMore } = useLoadItems(); const [infiniteRef, { rootRef }] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, // When there is an error, we stop infinite loading. // It can be reactivated by setting "error" state as undefined. disabled: Boolean(error), // `rootMargin` is passed to `IntersectionObserver`. // We can use it to trigger 'onLoadMore' when the sentry comes near to become // visible, instead of becoming fully visible on the screen. rootMargin: '0px 0px 400px 0px', }); return ( {items.map((item) => ( {item.value} ))} {hasNextPage && } ); } ``` -------------------------------- ### Build Reusable Wrapper Hook with Explicit Types Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt This example demonstrates how to create a reusable wrapper hook for infinite scrolling with explicit TypeScript types. It utilizes the `useInfiniteScroll` hook and its associated types to manage pagination state and loading logic. ```tsx import useInfiniteScroll, { type UseInfiniteScrollHookArgs, type UseInfiniteScrollHookResult, type UseInfiniteScrollHookRefCallback, type UseInfiniteScrollHookRootRefCallback, } from 'react-infinite-scroll-hook'; // Build a reusable wrapper hook with explicit types function usePagedList( fetchPage: (cursor: number) => Promise<{ data: T[]; hasNext: boolean }> ): { items: T[]; infiniteRef: UseInfiniteScrollHookRefCallback; rootRef: UseInfiniteScrollHookRootRefCallback; } { const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [hasNextPage, setHasNextPage] = useState(true); async function loadMore() { setLoading(true); const result = await fetchPage(items.length); setItems((prev) => [...prev, ...result.data]); setHasNextPage(result.hasNext); setLoading(false); } const args: UseInfiniteScrollHookArgs = { loading, hasNextPage, onLoadMore: loadMore }; const [infiniteRef, { rootRef }]: UseInfiniteScrollHookResult = useInfiniteScroll(args); return { items, infiniteRef, rootRef }; } ``` -------------------------------- ### Disable and Re-enable Infinite Scrolling with Error Handling Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Use the `disabled` option to pause infinite scrolling, for example, after a fetch error. Restore scrolling by toggling the flag back to `false`. The hook respects the current value on every render. ```tsx 'use client'; import { useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; export default function WithErrorHandling() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { await new Promise((_, reject) => setTimeout(() => reject(new Error('Network error')), 800), ); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setLoading(false); } } const [infiniteRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, // Scroll stops here; clear the error state to re-enable it disabled: Boolean(error), }); return (
    {items.map((item, idx) =>
  • {item}
  • )}
{error && (

Error: {error.message}

{/* Clear error to re-enable the IntersectionObserver */}
)} {hasNextPage && !error && (
{loading ? 'Loading…' : ''}
)}
); } ``` -------------------------------- ### Add a New Contributor Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Uses the all-contributors-cli to manage the list of contributors. Run this command and follow the prompts to add a new contributor. ```bash npm run contributors:add ``` -------------------------------- ### Build the Package Bundle Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Builds the package bundle for react-infinite-scroll-hook, creating or updating the `packages/react-infinite-scroll-hook/dist` folder. This is a prerequisite for prepublish checks. ```bash npm run build:bundle ``` -------------------------------- ### Run Prepublish Checks with Publint and Are the Types Wrong Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Perform prepublish checks using Publint and Are the Types Wrong (ATTW) to ensure the package is compatible with ESM and CJS clients. These commands target the react-infinite-scroll-hook package. ```bash # For `publint` npm run publint -w react-infinite-scroll-hook # For `Are the Types Wrong` npm run attw -w react-infinite-scroll-hook ``` -------------------------------- ### Publish the Package to npm Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Publishes the latest version of the react-infinite-scroll-hook package to the npm registry. Ensure versioning is updated before running this command. ```bash npm publish -w react-infinite-scroll-hook ``` -------------------------------- ### Run Individual Code Quality Tools Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Manually run specific code quality tools like ESLint, Prettier, or TypeScript checks and fixes. ```bash # ESLint checks npm run lint # ESLint fixes npm run lint:fix # Prettier checks npm run format # Prettier fixes npm run format:fix # TypeScript checks npm run typecheck # There is no auto-fix script for TypeScript. ``` -------------------------------- ### useInfiniteScroll Hook Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt The core `useInfiniteScroll` hook accepts a configuration object and returns a tuple containing a ref callback for the sentry element and an optional ref callback for the scrollable container. ```APIDOC ## useInfiniteScroll(args) ### Description The single exported hook. It accepts a configuration object and returns `[infiniteRef, { rootRef }]`. Attach `infiniteRef` to the sentry element at the tail (or head for reverse scroll) of your list. `rootRef` is only needed when using a scrollable container instead of the window. ### Type Signature ```typescript useInfiniteScroll(args: UseInfiniteScrollHookArgs): UseInfiniteScrollHookResult ``` ### Arguments (`UseInfiniteScrollHookArgs`) - **loading** (boolean) – `true` while a fetch is in-flight - **hasNextPage** (boolean) – `false` when all pages are loaded - **onLoadMore** (() => unknown) – called to fetch the next page - **rootMargin**? (string) – passed to IntersectionObserver (e.g. "0px 0px 400px 0px") - **disabled**? (boolean) – stops the observer (use on error) - **delayInMs**? (number) – debounce delay in ms (default: 100) ### Return Value (`UseInfiniteScrollHookResult`) - **[ref: UseInfiniteScrollHookRefCallback, { rootRef: UseInfiniteScrollHookRootRefCallback }]** - `ref`: A callback to attach to the sentry element. - `rootRef`: A callback to attach to the scrollable container (optional). ``` -------------------------------- ### Create a Tarball of the Package Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Creates a tarball of the react-infinite-scroll-hook package, which represents the content that can be uploaded to npm. This is useful for inspecting the package contents before publishing. ```bash npm pack -w react-infinite-scroll-hook ``` -------------------------------- ### Check for Dependency Updates Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Uses npm-check-updates to check for newer versions of project dependencies. This command launches an interactive CLI. ```bash npm run updates ``` -------------------------------- ### Reverse Horizontal Scroll with Scroll Anchoring Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Combines root ref composition with useLayoutEffect-based scroll anchoring for right-to-left infinite loading in a horizontal container. Ensure the scrollable element has overflow-x: auto and a maxWidth. ```tsx 'use client'; import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; export default function ReverseHorizontalScrollPage() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { await new Promise((r) => setTimeout(r, 600)); const next = Array.from({ length: 10 }, (_, i) => `Card ${items.length + i}`); setItems((prev) => [...prev, ...next]); setHasNextPage(items.length + next.length < 80); } catch (err) { setError(err instanceof Error ? err : new Error('Failed')); } finally { setLoading(false); } } const [infiniteRef, { rootRef }] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), }); const scrollableRootRef = useRef(null); const lastScrollDistanceToRightRef = useRef(0); const reversedItems = useMemo(() => [...items].reverse(), [items]); useLayoutEffect(() => { const root = scrollableRootRef.current; if (root) { root.scrollLeft = root.scrollWidth - lastScrollDistanceToRightRef.current; } }, [reversedItems, rootRef]); // Compose both refs onto the same container element const rootRefSetter = useCallback( (node: HTMLDivElement) => { rootRef(node); scrollableRootRef.current = node; }, [rootRef], ); const handleScroll = useCallback(() => { const root = scrollableRootRef.current; if (root) { lastScrollDistanceToRightRef.current = root.scrollWidth - root.scrollLeft; } }, []); return (
{/* Sentry at the LEFT edge for reverse horizontal loading */} {hasNextPage && (
{loading ? '…' : ''}
)} {reversedItems.map((item, idx) => (
{item}
))}
); } ``` -------------------------------- ### Reverse Vertical Scroll with Chat-like Interface Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Use this pattern for chat interfaces where new content loads at the top. Ensure the sentry is at the top, items are reversed, and `useLayoutEffect` maintains scroll position. ```tsx 'use client'; import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; export default function ReverseVerticalScrollPage() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { await new Promise((r) => setTimeout(r, 800)); const next = Array.from({ length: 10 }, (_, i) => `Message ${items.length + i}`); setItems((prev) => [...prev, ...next]); setHasNextPage(items.length + next.length < 60); } catch (err) { setError(err instanceof Error ? err : new Error('Failed')); } finally { setLoading(false); } } const [infiniteRef, { rootRef }] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), }); // Keep a ref to the scrollable container so we can read/set scrollTop const scrollableRootRef = useRef(null); const lastScrollDistanceToBottomRef = useRef(0); const reversedItems = useMemo(() => [...items].reverse(), [items]); // Restore scroll position after new items are prepended useLayoutEffect(() => { const root = scrollableRootRef.current; if (root) { root.scrollTop = root.scrollHeight - lastScrollDistanceToBottomRef.current; } }, [reversedItems, rootRef]); // Combine rootRef (for IntersectionObserver) with our local ref const rootRefSetter = useCallback( (node: HTMLDivElement) => { rootRef(node); scrollableRootRef.current = node; }, [rootRef], ); const handleScroll = useCallback(() => { const root = scrollableRootRef.current; if (root) { lastScrollDistanceToBottomRef.current = root.scrollHeight - root.scrollTop; } }, []); return (
{/* Sentry at the TOP — triggers loading when user scrolls to the top */} {hasNextPage && (
{loading ? 'Loading older messages…' : ''}
)}
    {reversedItems.map((item, idx) =>
  • {item}
  • )}
); } ``` -------------------------------- ### Run Code Quality Checks Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Executes automated code quality checks including ESLint, Prettier, and TypeScript. These checks run automatically before commits via husky and lint-staged. ```bash npm run codequality ``` -------------------------------- ### Import and Type Signature for useInfiniteScroll Hook Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Imports necessary types and the core hook from the 'react-infinite-scroll-hook' package. Shows the full type signature for the hook's arguments and return value. ```tsx import useInfiniteScroll, type UseInfiniteScrollHookArgs, type UseInfiniteScrollHookResult, type UseInfiniteScrollHookRefCallback, type UseInfiniteScrollHookRootRefCallback from 'react-infinite-scroll-hook'; // Full type signature // useInfiniteScroll(args: UseInfiniteScrollHookArgs): UseInfiniteScrollHookResult // // UseInfiniteScrollHookArgs: // loading boolean – true while a fetch is in-flight // hasNextPage boolean – false when all pages are loaded // onLoadMore () => unknown – called to fetch the next page // rootMargin? string – passed to IntersectionObserver (e.g. "0px 0px 400px 0px") // disabled? boolean – stops the observer (use on error) // delayInMs? number – debounce delay in ms (default: 100) // // UseInfiniteScrollHookResult: // [ref: UseInfiniteScrollHookRefCallback, { rootRef: UseInfiniteScrollHookRootRefCallback }] ``` -------------------------------- ### Run Code Quality Checks with Auto-Fixes Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Runs automated code quality checks and attempts to auto-fix any issues found. This command enables fixes for auto-fixable issues. ```bash npm run codequality:fix ``` -------------------------------- ### Dry Run Package Tarball Creation Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Checks the contents of the tarball for the react-infinite-scroll-hook package without actually creating the file. This is a way to preview what would be published. ```bash npm pack --dry-run -w react-infinite-scroll-hook ``` -------------------------------- ### Auto-Correct Package.json Errors Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Automatically corrects common errors in the `package.json` file for the react-infinite-scroll-hook package. The `npm publish` command also performs these auto-fixes. ```bash npm pkg fix -w react-infinite-scroll-hook ``` -------------------------------- ### Configure `delayInMs` for Debouncing Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Adjust the `delayInMs` option to control the debounce time for `onLoadMore`. Increase for slower render pipelines or decrease for faster perceived response. A delay of 0 ms provides the minimal delay. ```tsx import useInfiniteScroll from 'react-infinite-scroll-hook'; // Increase delay for virtualized lists where layout shifts are larger const [infiniteRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, delayInMs: 300, // wait 300 ms before invoking onLoadMore }); // Minimal delay for simple lists with small items const [fastRef] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, delayInMs: 0, }); ``` -------------------------------- ### Bump Package Version (Minor) Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Increments the minor version number of the react-infinite-scroll-hook package (e.g., 0.0.x to 0.1.0). Use this for backward-compatible changes. ```bash npm version minor -w react-infinite-scroll-hook ``` -------------------------------- ### Bump Package Version (Major) Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Increments the major version number of the react-infinite-scroll-hook package (e.g., 0.x.y to 1.0.0). Use this for breaking changes. ```bash npm version major -w react-infinite-scroll-hook ``` -------------------------------- ### Bump Package Version (Patch) Source: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/CONTRIBUTING.md Increments the patch version number of the react-infinite-scroll-hook package (e.g., 0.0.0 to 0.0.1). This is typically done before publishing a minor release. ```bash npm version patch -w react-infinite-scroll-hook ``` -------------------------------- ### Horizontal Element Scroll with React Infinite Scroll Hook Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt This hook functions identically for horizontal scrolling. Style your container with `overflow-x: auto` and lay out items in a row. Place the sentry at the right edge of the list. ```tsx 'use client'; import { useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; export default function HorizontalElementScrollPage() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { await new Promise((r) => setTimeout(r, 600)); const next = Array.from({ length: 10 }, (_, i) => `Card ${items.length + i}`); setItems((prev) => [...prev, ...next]); setHasNextPage(items.length + next.length < 80); } catch (err) { setError(err instanceof Error ? err : new Error('Failed')); } finally { setLoading(false); } } const [infiniteRef, { rootRef }] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), }); return (
{items.map((item, idx) => (
{item}
))} {/* Sentry placed at the right edge for horizontal scrolling */} {hasNextPage && (
{loading ? '…' : ''}
)}
); } ``` -------------------------------- ### Vertical Element Scroll with React Infinite Scroll Hook Source: https://context7.com/onderonur/react-infinite-scroll-hook/llms.txt Use this when your list is inside a scrollable div. Destructure `rootRef` and attach it to the container to scope the IntersectionObserver. ```tsx 'use client'; import { useState } from 'react'; import useInfiniteScroll from 'react-infinite-scroll-hook'; export default function VerticalElementScrollPage() { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); const [hasNextPage, setHasNextPage] = useState(true); const [error, setError] = useState(); async function loadMore() { setLoading(true); try { await new Promise((r) => setTimeout(r, 800)); // simulate network const next = Array.from({ length: 10 }, (_, i) => `Item ${items.length + i}`); setItems((prev) => [...prev, ...next]); setHasNextPage(items.length + next.length < 60); } catch (err) { setError(err instanceof Error ? err : new Error('Failed')); } finally { setLoading(false); } } // rootRef scopes the IntersectionObserver to the scrollable div const [infiniteRef, { rootRef }] = useInfiniteScroll({ loading, hasNextPage, onLoadMore: loadMore, disabled: Boolean(error), }); return ( // Attach rootRef to the scrollable container
    {items.map((item, idx) =>
  • {item}
  • )}
{/* Sentry at the bottom of the scrollable container */} {hasNextPage && (
{loading ? 'Loading…' : ''}
)} {error &&

Error: {error.message}

}
); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.