Skip to content

Integration with pagination on backend #78

@cherniavskii

Description

@cherniavskii

Hi Tanner!

I've found that integration React Query with backend paginated APIs ("prev/next page", not load more/infinite scroll) is pretty difficult.

There's an example in readme, in which query variables are used for that:

function Todos() {
  const [page, setPage] = useState(0)

  const { data, isLoading, error } = useQuery(
    ['todos', { page }],
    fetchTodoList
  )

  const onNextPage = () => {
    setPage(page => page + 1)
  }

  return (
    <>
      {/* ... */}
      <button onClick={onNextPage}>Load next page</button>
    </>
  )
}

But i'm not sure, that this is the proper way to handle that.

Here are my doubts:

  • after changing the page - a new query is created, so data is null. This leads to blinking, since data from previous page aren't available yet, so UX experience is poor in this case
  • this pattern doesn't work with SSR. Consider this example:
import React from "react";
import fetch from "../lib/fetch";
import { useQuery } from "react-query";

function Component({ initialData }) {
  const [page, setPage] = React.useState(1);
  const { data } = useQuery(
    ["data", { page }],
    async () => await fetch(`/api/data?page=${page}`),
    { initialData }
  );
  // ...
}

Component.getInitialProps = async () => {
  const data = await fetch('/api/data?page=1');
  return { initialData: data };
};

When page changes, new query is created and it's data is set to initialData.
In this case user sees initialData before new query data is fetched:

Screen Recording 2019-12-11 at 15 57 44

Here's reproducible example: https://codesandbox.io/s/react-query-pagination-with-ssr-03tzu

Workaround

I've managed to workaround both issues by:

  • not using page as query variable
  • calling refetchQuery every time page changes
function Component({ initialData }) {
  const [page, setPage] = React.useState(1);
  const { data } = useQuery(
    "data",
    async () => await fetch(`/api/data?page=${page}`),
    { initialData }
  );

  React.useEffect(() => {
    refetchQuery('data');
  }, [page]);

  // ...
}

This did the trick, but:

  • it's not obvious
  • it doesn't feel right to me

Question

What is you experience in integration React Query with backend pagination and Is there idiomatic way to it?

Will be happy to discuss!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions