Blog>
Snippets

Handling Paginated Queries with React Query

Show how to use React Query for handling paginated API responses, including fetching, caching, and managing the pagination state.
import { useInfiniteQuery } from 'react-query';
import axios from 'axios';

const fetchProjects = async ({ pageParam = 1 }) => {
  const res = await axios.get(`/api/projects?page=${pageParam}`);
  return res.data;
};

function Projects() {
  const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, status } = useInfiniteQuery('projects', fetchProjects, {
    getNextPageParam: (lastPage, pages) => lastPage.nextPage ?? false
  });

  if (status === 'loading') return <p>Loading...</p>;
  if (status === 'error') return <p>Error: {error.message}</p>;

  return (
    <>
      {data.pages.map((page, i) => (
        <React.Fragment key={i}>
          {page.items.map(project => (
            <p key={project.id}>{project.name}</p>
          ))}
        </React.Fragment>
      ))}
      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage
          ? 'Loading more...'
          : hasNextPage
          ? 'Load More'
          : 'Nothing more to load'}
      </button>
      <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div>
    </>
  );
}
This code snippet demonstrates how to use React Query's useInfiniteQuery hook to handle paginated API responses for a "projects" endpoint. It fetches pages of projects, caches them, and manages the pagination state, allowing to fetch the next page. It also handles loading, error states, and indicates when it's fetching new data.