Blog>
Snippets

Implementing Infinite Scroll with useInfiniteQuery

Provide an example of a custom hook that uses useInfiniteQuery to fetch data in paginated format and supports an infinite scroll feature in a React component.
import { useInfiniteQuery } from '@tanstack/react-query';
import axios from 'axios';
Imports the useInfiniteQuery hook from React Query and axios for making HTTP requests.
const fetchPosts = ({ pageParam = 1 }) => axios.get(`/api/posts?page=${pageParam}`).then(res => res.data);
Defines a function to fetch posts from an API. It accepts a pageParam which defaults to 1 if not provided.
function useInfinitePosts() {
  return useInfiniteQuery(['posts'], fetchPosts, {
    getNextPageParam: (lastPage, pages) => lastPage.nextPage ?? false
  });
}
Creates a custom hook using useInfiniteQuery to fetch posts in a paginated manner. It configures the getNextPageParam option to determine the next page based on the last page's data.
import React from 'react';
import { useInfinitePosts } from './useInfinitePosts';
In a React component, imports the custom hook.
function PostsComponent() {
  const { data, fetchNextPage, hasNextPage } = useInfinitePosts();

  const observer = React.useRef();
  const lastPostElementRef = React.useCallback(node => {
    if (observer.current) observer.current.disconnect();
    observer.current = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && hasNextPage) {
        fetchNextPage();
      }
    });
    if (node) observer.current.observe(node);
  }, [fetchNextPage, hasNextPage]);

  return (
    <div>
      {data?.pages.map((page, i) => (
        <React.Fragment key={i}>
          {page.posts.map((post, index) => (
            <div key={post.id} ref={index + 1 === page.posts.length ? lastPostElementRef : null}>{post.title}</div>
          ))}
        </React.Fragment>
      ))}
    </div>
  );
}
Implements the infinite scroll feature in a React component. Uses the useInfinitePosts hook to fetch data and automatically fetches the next page of posts as the user scrolls down, by using an IntersectionObserver on the last post of the current list.