Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-query: how to paginate with useInfiniteQuery

Tags:

reactjs

I would like to use react-query's useInfiniteQuery. Everything seems clear but the pagination, part.

The documentation exemple is:

export default () => {
  const {
    status,
    data,
    error,
    isFetching,
    isFetchingMore,
    fetchMore,
    canFetchMore,
  } = useInfiniteQuery(
    'projects',
    async (key, nextId = 0) => {
      const { data } = await axios.get('/api/projects?cursor=' + nextId)
      return data
    },
    {
      getFetchMore: lastGroup => lastGroup.nextId,
    }
  )

I understand what it does. projects is the id of the query, used for the cache, and then there is the function, that performs an api call. Now what about the nextId variable? It starts at zero, so the backend will know it must only return results from 0 to x (can we also pass a dynamic limit by the way?). But when fetchMore() - the function to trig the query again - is called, how on earth does useInfiniteQuery knows it should increment nextId?

like image 270
DoneDeal0 Avatar asked Jun 01 '20 10:06

DoneDeal0


People also ask

How do I Refetch data in react query?

Using auto refetching in React Query To use the auto refetch mode, you can pass an optional parameter to the React Query hook called refetchInterval . The value is in milliseconds. const { isLoading, data } = useQuery( 'vehicle', async () => { const { data } = await axios.

What is useMutation in react query?

Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. For this purpose, React Query exports a useMutation hook. Here's an example of a mutation that adds a new todo to the server: tsx.


1 Answers

I'm trying to make an infinite scroll with rick and morty API and here's how I implemented it:

Your function (getCharacters) should accept a key and a prop (nextPage) and returns an object that includes the data (data) from your fetch and the page identifier (nextPage) plus 1.

const getCharacters = async (key, nextPage = 1) => {
  const res = await fetch(`${BASE_URL}/character/?page=${nextPage}`);
  const { results } = await res.json();
  return {
    data: results,
    nextPage: nextPage + 1,
  };
};

const { status, data, fetchMore } = useInfiniteQuery(
  'characters',
  getCharacters,
  {
    getFetchMore: (lastGroup, allGroups) => lastGroup.nextPage, // nextPage because we named it nextPage
  }
);

const paginatedData = [];
data.forEach((page) => {
  page.data.forEach((char) => {
    paginatedData.push(char);
  });
});

console.log(paginatedData) // The whole data

Update:

A better example using Rick and Morty API

async function getCharacters(page: number): Promise<Response> {
    const response = await fetch('https://rickandmortyapi.com/api/character?page=' + page)
    const characters = (await response.json())
    return characters;
}

const { ... } = useInfiniteQuery(['characters'], ({ pageParam = 1 }) => getCharacters(pageParam), {
  getNextPageParam: (lastPage) => {
    const nextUrl = lastPage.info.next
    if (nextUrl) {
      // Return next page number
      return Number(nextUrl.charAt(nextUrl.length - 1))
    }
    // Return false means no next page
    return false
  }
})
like image 59
wobsoriano Avatar answered Nov 08 '22 20:11

wobsoriano