0Pricing
React Academy · Lesson

Infinite Scroll & Pagination with useInfiniteQuery

Fetch paginated data and load more pages seamlessly with useInfiniteQuery.

Infinite Scroll & Pagination with useInfiniteQuery is a free React Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Welcome

In this lesson you will use useInfiniteQuery to fetch paginated data and implement an infinite scroll pattern that loads more pages as the user scrolls.

What Is useInfiniteQuery?

useInfiniteQuery fetches data in 'pages'. Each page is fetched separately and appended to the cached list. It provides fetchNextPage, hasNextPage, and isFetchingNextPage utilities.

Basic Setup

Define initialPageParam and getNextPageParam. The queryFn receives the current pageParam and must return a page of results.
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
  queryKey: ['posts'],
  queryFn: ({ pageParam }) =>
    fetch('/api/posts?cursor=' + pageParam).then(r => r.json()),
  initialPageParam: 0,
  getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
});

getNextPageParam

getNextPageParam receives the last fetched page and all pages. Return the next page cursor/number, or undefined/null to signal there are no more pages (sets hasNextPage to false).
getNextPageParam: (lastPage, allPages) => {
  return lastPage.hasMore ? lastPage.nextCursor : undefined;
}

Rendering All Pages

data.pages is an array of page results. Flatten them to render all items as a continuous list.
const allPosts = data.pages.flatMap(page => page.items);

return (
  <ul>
    {allPosts.map(post => <li key={post.id}>{post.title}</li>)}
  </ul>
);

Load More Button

Add a 'Load More' button that calls fetchNextPage. Disable it when there are no more pages or a fetch is in progress.
<button
  onClick={() => fetchNextPage()}
  disabled={!hasNextPage || isFetchingNextPage}
>
  {isFetchingNextPage ? 'Loading...' : hasNextPage ? 'Load More' : 'No more posts'}
</button>

Infinite Scroll with IntersectionObserver

Attach an IntersectionObserver to a sentinel div at the bottom of the list. When it enters the viewport, call fetchNextPage automatically.
const observerRef = useRef();
useEffect(() => {
  const observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting && hasNextPage) fetchNextPage();
  });
  if (observerRef.current) observer.observe(observerRef.current);
  return () => observer.disconnect();
}, [hasNextPage, fetchNextPage]);

<div ref={observerRef} />  {/* sentinel at bottom */}

Bidirectional Infinite Scroll

For chat apps, support scrolling in both directions: fetchNextPage for older messages and getPreviousPageParam/fetchPreviousPage for newer messages.

Page vs Cursor Based Pagination

Offset/page-based: initialPageParam=1, getNextPageParam returns lastPage.page + 1. Cursor-based: use the last item's ID as cursor. Cursor-based is more stable for live data.
// Offset-based
getNextPageParam: (lastPage) => lastPage.page + 1

Refetching Infinite Queries

Calling invalidateQueries on an infinite query refetches only the first page. To refetch all pages (e.g. after a new post is added), use queryClient.resetQueries or refetchType: 'all'.

Quick Check

What must getNextPageParam return to signal there are no more pages to load?

Recap

useInfiniteQuery accumulates pages in data.pages. Flatten with flatMap to render. Use getNextPageParam returning undefined to stop. Trigger fetchNextPage on button click or IntersectionObserver for infinite scroll.

Course Complete

Congratulations! You finished **React Query: Server State Management**. You can now fetch, cache, mutate, paginate, and scroll infinitely with TanStack Query.

Frequently asked questions

Is the “Infinite Scroll & Pagination with useInfiniteQuery” lesson free?

Yes — the full text of “Infinite Scroll & Pagination with useInfiniteQuery” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Infinite Scroll & Pagination with useInfiniteQuery”?

Fetch paginated data and load more pages seamlessly with useInfiniteQuery. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Infinite Scroll & Pagination with useInfiniteQuery” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Setting Up React Query & QueryClient
  2. Caching, Stale Time & Background Refetching
  3. Mutations with useMutation
  4. Infinite Scroll & Pagination with useInfiniteQuery
← Back to React Academy