LoginSignup
7
1

More than 1 year has passed since last update.

React Queryのページネーションがとても良かった

Last updated at Posted at 2022-05-10

はじめに

結論から言うとkeepPreviousDataというオプションが非常に良かったです。

  • The data from the last successful fetch available while new data is being requested, even though the query key has changed.
  • When the new data arrives, the previous data is seamlessly swapped to show the new data.
  • isPreviousData is made available to know what data the query is currently providing you

クエリが変わっても、最後に取得したデータは新しいデータが要求されている間に利用可能で、新しいデータの取得が完了すると以前のデータはシームレスに入れ替わり、新しいデータが表示されます。

検証に使用したサンプルコードを置いておきます。
※検証ではreact-queryとtailwindcssを使用してますので、下記サンプルを実際に使用するには設定が必要です。

$ npm i react-query

import { useState } from 'react'
import { useQuery } from 'react-query'

type Post = {
  usedId: number
  id: string
  title: string
  body: string
}

const Paginate = () => {
  const [page, setPage] = useState(1)

  const fetchProjects = (page = 1) =>
    fetch(
      `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
    ).then((res) => res.json())

  const { isLoading, isError, error, data, isFetching, isPreviousData } =
    useQuery<Post[], Error>(['projects', page], () => fetchPosts(page), {
      keepPreviousData: true,
    })

  return (
    <div className="flex min-h-screen w-screen flex-1 flex-col items-center justify-center">
      {isLoading ? (
        <div>Loading...</div>
      ) : isError ? (
        <div>Error: {error.message}</div>
      ) : (
        <div>
          {data?.map((post) => (
            <p key={post.id}>
              {post.id}. {post.title}
            </p>
          ))}
        </div>
      )}
      <span className="pt-12">Current Page: {page}</span>
      <div className="py-12">
        <button
          className="rounded-md bg-blue-300  p-2 text-white"
          onClick={() => setPage((old) => Math.max(old - 1, 0))}
          disabled={page === 1}
        >
          Previous Page
        </button>
        <button
          className="ml-4 rounded-md bg-red-300  p-2 text-white"
          onClick={() => {
            if (!isPreviousData && data) {
              setPage((old) => old + 1)
            }
          }}
          disabled={isPreviousData || !data}
        >
          Next Page
        </button>
      </div>
      {isFetching ? <span> Loading...</span> : null}
    </div>
  )
}

export default Paginate

keepPreviousData:falseの場合(デフォルト)

画面収録_2022-05-10_10_32_45_AdobeCreativeCloudExpress.gif

このようにページが切り替わる度にローディングが発生しています。

keepPreviousData:trueの場合

画面収録_2022-05-10_10_33_45_AdobeCreativeCloudExpress.gif

このように新しいデータの取得ができるまで、以前のデータを表示し、取得が完了すると切り替わるというような挙動になります。

さいごに

以上になります。
すごく細部までごだわっている感じがいいなあと思いました(小並感)

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1