DEV Community

Cover image for Infinite loading with React Query
Chris Bongers
Chris Bongers

Posted on • Updated on • Originally published at daily-dev-tips.com

Infinite loading with React Query

You might find yourself in a position where you have a list so long you want to give the option to load it in stages.

We call this an infinite loading list.
In the example below, you see a Pokemon list that will show 10 Pokemon at a time.
Once we click the button, it will load the next 10, and so forth.

Infinite loading with React Query

Let's see how we can achieve this by using React Query.

React Query infinite loading

Depending on your API, you might have a different way of identifying how the next cursor/page is defined.

For the Pokemon API, we get the following result:

{
    count: 1118
    next: "https://pokeapi.co/api/v2/pokemon?offset=10&limit=10"
    previous: null
    results: []
}
Enter fullscreen mode Exit fullscreen mode

We see that we get the whole next URL as an option, knowing this means we can define the first URL and keep swapping that one out.

Let's set up our function that can query this data.

const fetchPokemon = async ({
  pageParam = 'https://pokeapi.co/api/v2/pokemon?offset=0&limit=10',
}) => {
  const request = await fetch(pageParam);
  const {results, next} = await request.json();
  return {response: results, nextPage: next};
};
Enter fullscreen mode Exit fullscreen mode

As you can see in the function above, we defined the first initial page param.
Then we fetch this page and extract the results array and the next string from it.

Then we return those two things.

As for our component, we first have to make sure to import the useInfiniteQuery from React Query.

import {QueryClient, QueryClientProvider, useInfiniteQuery} from 'react-query';
Enter fullscreen mode Exit fullscreen mode

Then we can set up this infinite query as we have seen before by using the regular react query.

const {data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage} =
  useInfiniteQuery('pokemon', fetchPokemon, {
    getNextPageParam: (lastPage) => lastPage.nextPage,
  });
Enter fullscreen mode Exit fullscreen mode

Here, we still use a query key, pokemon, and then call the function we just created.

The new thing here is that we extract more elements from the query and pass a new function getNextPageParam in this function, we define the next page parameter.

We set this as nextPage, so we need to pass this on. React query will do all the heavy calculations to determine if there is more to load and how far we are.

The data is slightly different from what we saw before since infinite query results are all mapped in their respective pages.
You will receive a page for every request the infinite query has made.

{data.pages.map((group, i) =>
  // Use the group data
)}
Enter fullscreen mode Exit fullscreen mode

The group data is the actual data inside each page. We can simply loop over that as we did with react query.

{
  data.pages.map((group, i) => group.response.map((pokemon) => <li>{pokemon.name}</li>));
}
Enter fullscreen mode Exit fullscreen mode

Loading more data with React Infinite Query

Now that we have our initial data loaded, we want to have a button to load more data if there is any.

We exported some extra data from the infinite query, and this is exactly what we'll use it for.

  • fetchNextPage: This function can fetch the next page based on what we defined to be the parameter.
  • hasNextPage: Determines if there is the next page
  • isFetchingNextPage: Determine if we are busy fetching a new page

Now let's add a button that can fetch this data for us.

<button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage}>
  {isFetchingNextPage
    ? 'Loading more...'
    : hasNextPage
    ? 'Load More'
    : 'Nothing more to load'}
</button>
Enter fullscreen mode Exit fullscreen mode

This button will fetch the next page once we click it, but it's disabled if we don't have the next page or it's loading one.

Then we change the button text based on the condition as well.

And there you go, we can now load infinite amounts of Pokemon, and React query will do all the heavy lifting.

Feel free to try it out in this Code Sandbox.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Top comments (2)

Collapse
 
ngnam profile image
NamNguyen
Collapse
 
dailydevtips1 profile image
Chris Bongers

Way more complicated to do this all by hand don't you think?
For me React Query really makes these things so much easier.