react-infinite-scroll-hook

repository·main·Indexed 19 days ago

https://github.com/onderonur/react-infinite-scroll-hook

A React hook for implementing infinite scrolling using the IntersectionObserver API. It triggers a callback when a 'sentry' element enters the viewport, supporting window scrolling, scrollable containers, and various scrolling directions. Compatible with React v19 (v6+) and older versions (v5).

Tokens
2.2K
Snippets
5
Records
11
Agent score
67%

What's inside react-infinite-scroll-hook

  1. How the infinite scroll hook works

    main

    The hook works by using an IntersectionObserver to monitor a "sentry" component. When this sentry component becomes visible (or approaches visibility based on rootMargin), the onLoadMore callback is triggered.

    Key Concepts:

    • Sentry Component: A component (like a loading indicator, an empty div, or the last item in a list) that must remain mounted as long as you want the observer to stay active. To prevent flickering and maintain layout consistency, it is recommended to keep the sentry mounted even if your loading state is false, provided there is still a next page to load.
    • Scrolling Direction: You can place the sentry at the bottom for vertical scrolling, at the top for chat-like interfaces, or use it for horizontal scrolling.
    • Browser Compatibility: The hook relies on IntersectionObserver. For older browsers, you may need to provide a polyfill.
  2. Use useInfiniteScroll for scrollable containers

    main

    If you want to use a specific element as the scrollable container instead of the document, use the rootRef returned by the hook and attach it to your container element.

    import useInfiniteScroll from 'react-infinite-scroll-hook';
    
    function VerticalElementScrollPage() {
      const { loading, items, hasNextPage, error, loadMore } = useLoadItems();
    
      const [infiniteRef, { rootRef }] = useInfiniteScroll({
        loading,
        hasNextPage,
        onLoadMore: loadMore,
        disabled: Boolean(error),
        rootMargin: '0px 0px 400px 0px',
      });
    
      return (
        <Scrollable ref={rootRef}>
          <List>
            {items.map((item) => (
              <ListItem key={item.key}>{item.value}</ListItem>
            ))}
          </List>
          {hasNextPage && <Loading ref={infiniteRef} />}
        </Scrollable>
      );
    }
  3. Use useInfiniteScroll for window scrolling

    main

    To implement infinite scrolling on the main window/document, use the useInfiniteScroll hook and attach the returned infiniteRef to your sentry component.

    import useInfiniteScroll from 'react-infinite-scroll-hook';
    
    function WindowScroll() {
      const { loading, items, hasNextPage, error, loadMore } = useLoadItems();
    
      const [infiniteRef] = useInfiniteScroll({
        loading,
        hasNextPage,
        onLoadMore: loadMore,
        // It can be reactivated by setting "error" state as undefined.
        disabled: Boolean(error),
        // rootMargin is passed to 'IntersectionObserver'.
        rootMargin: '0px 0px 400px 0px',
      });
    
      return (
        <div>
          <List>
            {items.map((item) => (
              <ListItem key={item.key}>{item.value}</ListItem>
            ))}
          </List>
          {hasNextPage && <Loading ref={infiniteRef} />}
        </div>
      );
    }
  4. Configure Prettier with import organization and Tailwind CSS support

    main

    The project uses Prettier for code formatting, extending the @vercel/style-guide/prettier configuration. It includes two specific plugins to manage imports and Tailwind CSS classes:

    1. prettier-plugin-organize-imports: Automatically organizes imports. To prevent the plugin from automatically removing unused imports (which can be considered a destructive code action), the organizeImportsSkipDestructiveCodeActions option is set to true.
    2. prettier-plugin-tailwindcss: Automatically sorts Tailwind CSS classes. This plugin must be placed last in the plugins array to ensure compatibility with other plugins.
    import styleguide from '@vercel/style-guide/prettier';
    
    const config = {
      ...styleguide,
      organizeImportsSkipDestructiveCodeActions: true,
      plugins: [
        ...styleguide.plugins,
        'prettier-plugin-organize-imports',
        'prettier-plugin-tailwindcss',
      ],
    };
    
    export default config;
  5. useInfiniteScroll configuration arguments

    main

    The useInfiniteScroll hook accepts the following configuration options:

    NameDescriptionTypeOptionalDefault Value
    loadingSome sort of "is fetching" info of the request.boolean
    hasNextPageIf the list has more items to load.boolean
    onLoadMoreThe callback function to execute when the 'onLoadMore' is triggered.VoidFunction
    rootMarginWe pass this to 'IntersectionObserver'. We can use it to configure when to trigger 'onLoadMore'.string
    disabledFlag to stop infinite scrolling. Can be used in case of an error etc too.boolean
    delayInMsHow long it should wait before triggering 'onLoadMore' (in milliseconds).number100
  6. Understand the return values of useInfiniteScroll

    main

    The useInfiniteScroll hook returns a tuple of type UseInfiniteScrollHookResult containing:

    1. UseInfiniteScrollHookRefCallback: A ref that should be attached to the element acting as the 'sentinel' (the element that triggers the load when it enters the viewport).
    2. An object containing { rootRef: UseInfiniteScrollHookRootRefCallback }: A rootRef that should be attached to the scrollable container element.
  7. Use the useInfiniteScroll hook

    main

    The useInfiniteScroll hook (exported as default) is the primary API for implementing infinite scrolling in React applications. It provides a way to detect when a user has scrolled to the bottom of a container and triggers a callback to load more content.

    To use it, you will typically need to interact with the following types:

    • UseInfiniteScrollHookResult: The object returned by the hook containing the scroll state and refs.
    • UseInfiniteScrollHookArgs: The configuration object passed to the hook.
    • UseInfiniteScrollHookRootRefCallback: A ref callback used to attach to the scrollable container element.
  8. Configure useInfiniteScroll arguments

    main

    The useInfiniteScroll hook accepts a UseInfiniteScrollHookArgs object with the following properties:

    PropertyTypeDescription
    loadingbooleanRequired. Indicates if a fetch request is currently in progress.
    hasNextPagebooleanRequired. Indicates if there are more items available to load.
    onLoadMore() => unknownRequired. The callback function to execute when the sentinel element becomes visible.
    rootMarginstringConfigures the IntersectionObserver margin. Controls how close the sentinel must be to the viewport before triggering.
    disabledbooleanOptional. If true, prevents onLoadMore from being triggered (e.g., during errors).
    delayInMsnumberOptional. A delay in milliseconds before triggering onLoadMore. Defaults to 100. This helps prevent rapid-fire triggers when new items are rendered.