3 min read React Query · Part 12 of 12

React Query - Infinite Queries

Hey Folks, Today it's time to learn how you can build an infinite query with React Query. To build...

#react #reactquery #reacthooks
Luca Del Puppo Luca Del Puppo
Article Series · Part 12 of 12 React Query
View full series (12)
  1. #10 Part 10
    Abort Request
  2. #11 Previous
    Paginated List
  3. #12 Reading now
    Infinite Queries
Browse all 12 parts in this series
  1. #1 useQuery
  2. #2 useMutation
  3. #3 useIsFetching & useIsMutation
  4. #4 DevTools
  5. #5 Authentication Flow
  6. #6 Filter Your Data
  7. #7 Enable Query
  8. #8 Keys & Prefetching
  9. #9 Improve user experience with optimistic update
  10. #10 Abort Request
  11. #11 Paginated List
  12. #12 Infinite Queries Current

Hey Folks,

Today it’s time to learn how you can build an infinite query with React Query.

To build an infinite query you have to use the useInfiniteQuery hook. This hook is similar to the useQuery but with some more properties to handle the infinite loading in the best way.

The key concepts, if you are working with useInfiniteQuery are:

  • Key : in this case, the key is unique for each page, useInfiniteQuery handles all the pages inside its state

  • page : each chunk of your infinite query is represented as a page and the first page returned by the useInfiniteQuery is undefined. This helps you to understand if it’s the first iteration or not.

  • hasNextPage : is a variable returned by the hook and its scope is to determine if another chunk exists or not

  • fetchNextPage : is a function used to fetch the next chunk

  • isLoading : is a flag that determines if there is a loading ongoing (The query has no data yet)

  • isFetching : is a flag that determines if there is a fetch request ongoing

  • getNextPageParam : this function is an option to pass at the hook and it is used to determine if there is another chunk or not after the response

ok, let’s see the code to be clearer

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

const fetchTodos = async (
  page: number,
  limit: number,
  signal: AbortSignal | undefined
): Promise<{
  totals: number;
  todos: Todo[];
}> => {
  const response = await fetch(`api/tasks?_page=${page + 1}&_limit=${limit}`, {
    signal,
  });
  if (!response.ok) {
    throw new ResponseError('Failed to fetch todos', response);
  }
  const todos: Todo[] = await response.json();
  const totals = Number.parseInt(
    response.headers.get('x-total-count') || '0',
    10
  );

  return {
    totals,
    todos,
  };
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  hasNext: boolean;
  next?: () => void;
}

export const useTodos = (): UseTodos => {
  const [limit] = useState<number>(5);

  const { data, hasNextPage, fetchNextPage, isLoading, isFetching, error } =
    useInfiniteQuery(
      [QUERY_KEY.todos],
      ({ signal, pageParam: page = 0 }) => fetchTodos(page, limit, signal),
      {
        refetchOnWindowFocus: false,
        retry: 2,
        getNextPageParam: (lastPage, pages) => {
          if (Math.ceil(lastPage.totals / limit) > pages.length)
            return pages.length;
          return undefined;
        },
      }
    );

  return {
    todos: data?.pages.flatMap(({ todos }) => todos) || [],
    isLoading,
    isFetching,
    error: mapError(error),
    next: fetchNextPage,
    hasNext: hasNextPage || false,
  };
};

As you can notice, the flow is very simple, the hook returns the current page or chunk, you have to handle the fetch request and then you can determine the result and if there is another chunk or not.
Another important thing to keep in mind is that the result of the useInfiniteQuery is an array and each element of the array contains the data of each chunk.

Ok, I suppose you have an idea of how Infinite Queries work in React Query, but if you want to deep into it don’t miss my youtube about it.

🎬 Watch / View Embedded Resource: https://www.youtube.com/watch?v=F1KD4GY1iws

I think thats all from this article.

This is the last post of this series, I hope you enjoyed the content and now you are aware of using ReactQuery in your React application.

See you soon folks
Bye Bye 👋

p.s. you can find the code of the video in the GitHub repository

Photo by Rahul Mishra on Unsplash

🎬 Watch / View Embedded Resource: https://dev.to/puppo

Luca Del Puppo

Written by Luca Del Puppo

Run, Code & Learn

AI Native Engineer at Nearform based in Povegliano (TV), Italy. Google Developer Expert in Web Technologies, GitKraken Ambassador, and Codemotion Ambassador.