Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Infinite Queries for Endless Scrolling | Advanced Query Patterns
TanStack Query Server State Management in React

bookInfinite Queries for Endless Scrolling

When building modern web applications, you often need to load large datasets without overwhelming the user or the server. Infinite scrolling is a popular pattern that loads more data as the user scrolls, creating a seamless browsing experience. TanStack Query offers a specialized hook, useInfiniteQuery, to implement this pattern efficiently in your React projects. This hook is designed for situations where you need to fetch data in chunks, such as social media feeds, product listings, or activity logs, and append new data as the user reaches the end of the current list.

The useInfiniteQuery hook differs from the regular useQuery by supporting pagination through pages of data and providing built-in helpers for fetching subsequent pages. A crucial part of this setup is the getNextPageParam function, which tells TanStack Query how to determine the next chunk of data to load based on the current set of results.

To see how this works in practice, imagine you are fetching a list of posts from an API that supports pagination. You want to load more posts as the user scrolls down. With useInfiniteQuery, you can handle this pattern by specifying how to fetch the next page and how to combine all loaded pages for display.

import { useInfiniteQuery } from "@tanstack/react-query";

const fetchPosts = async ({ pageParam = 0 }) => {
  const res = await fetch(
    `https://dummyjson.com/posts?limit=5&skip=${pageParam}`
  );

  if (!res.ok) {
    throw new Error("Failed to fetch posts");
  }

  return res.json();
};

export default function PostsList() {
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading,
    isError,
    error,
  } = useInfiniteQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
    getNextPageParam: (lastPage) => {
      const nextSkip = lastPage.skip + lastPage.limit;
      return nextSkip < lastPage.total ? nextSkip : undefined;
    },
  });

  if (isLoading) return <p>Loading posts...</p>;
  if (isError) return <p>Error: {error.message}</p>;

  return (
    <div>
      {data.pages.map((page) =>
        page.posts.map((post) => (
          <div key={post.id}>{post.title}</div>
        ))
      )}

      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage
          ? "Loading more..."
          : hasNextPage
          ? "Load More"
          : "No more posts"}
      </button>
    </div>
  );
}

In this example, the fetchPosts function retrieves posts from the server. The getNextPageParam callback checks the server response (lastPage) to determine if there is another page to fetch, returning the next page number or false if there are no more pages. The UI renders all loaded posts and provides a button to load more, which is disabled and labeled appropriately based on loading state and whether more data is available.

Handling loading, error, and end-of-list states is essential for a smooth infinite scrolling experience. When the query is loading, you should display a loading indicator. If an error occurs, show a helpful error message. As more data is loaded, you need to check if there are additional pages; if not, inform the user that they have reached the end of the list. The useInfiniteQuery hook provides properties like isLoading, isFetchingNextPage, hasNextPage, and status to help you manage these states and update your UI accordingly. Always ensure that your UI communicates clearly with the user about what is happening—whether more data is loading, an error has occurred, or no more data is available.

question mark

Which statement best describes the role of the getNextPageParam function in the useInfiniteQuery hook, as shown in the example above?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 4. Chapitre 3

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

Suggested prompts:

Can you explain how the getNextPageParam function works in this example?

What happens if the API returns an error or unexpected data?

How can I trigger loading more posts automatically as the user scrolls, instead of using a button?

bookInfinite Queries for Endless Scrolling

Glissez pour afficher le menu

When building modern web applications, you often need to load large datasets without overwhelming the user or the server. Infinite scrolling is a popular pattern that loads more data as the user scrolls, creating a seamless browsing experience. TanStack Query offers a specialized hook, useInfiniteQuery, to implement this pattern efficiently in your React projects. This hook is designed for situations where you need to fetch data in chunks, such as social media feeds, product listings, or activity logs, and append new data as the user reaches the end of the current list.

The useInfiniteQuery hook differs from the regular useQuery by supporting pagination through pages of data and providing built-in helpers for fetching subsequent pages. A crucial part of this setup is the getNextPageParam function, which tells TanStack Query how to determine the next chunk of data to load based on the current set of results.

To see how this works in practice, imagine you are fetching a list of posts from an API that supports pagination. You want to load more posts as the user scrolls down. With useInfiniteQuery, you can handle this pattern by specifying how to fetch the next page and how to combine all loaded pages for display.

import { useInfiniteQuery } from "@tanstack/react-query";

const fetchPosts = async ({ pageParam = 0 }) => {
  const res = await fetch(
    `https://dummyjson.com/posts?limit=5&skip=${pageParam}`
  );

  if (!res.ok) {
    throw new Error("Failed to fetch posts");
  }

  return res.json();
};

export default function PostsList() {
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading,
    isError,
    error,
  } = useInfiniteQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
    getNextPageParam: (lastPage) => {
      const nextSkip = lastPage.skip + lastPage.limit;
      return nextSkip < lastPage.total ? nextSkip : undefined;
    },
  });

  if (isLoading) return <p>Loading posts...</p>;
  if (isError) return <p>Error: {error.message}</p>;

  return (
    <div>
      {data.pages.map((page) =>
        page.posts.map((post) => (
          <div key={post.id}>{post.title}</div>
        ))
      )}

      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage
          ? "Loading more..."
          : hasNextPage
          ? "Load More"
          : "No more posts"}
      </button>
    </div>
  );
}

In this example, the fetchPosts function retrieves posts from the server. The getNextPageParam callback checks the server response (lastPage) to determine if there is another page to fetch, returning the next page number or false if there are no more pages. The UI renders all loaded posts and provides a button to load more, which is disabled and labeled appropriately based on loading state and whether more data is available.

Handling loading, error, and end-of-list states is essential for a smooth infinite scrolling experience. When the query is loading, you should display a loading indicator. If an error occurs, show a helpful error message. As more data is loaded, you need to check if there are additional pages; if not, inform the user that they have reached the end of the list. The useInfiniteQuery hook provides properties like isLoading, isFetchingNextPage, hasNextPage, and status to help you manage these states and update your UI accordingly. Always ensure that your UI communicates clearly with the user about what is happening—whether more data is loading, an error has occurred, or no more data is available.

question mark

Which statement best describes the role of the getNextPageParam function in the useInfiniteQuery hook, as shown in the example above?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 4. Chapitre 3
some-alt