はじめに
結論から言うと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
の場合(デフォルト)
このようにページが切り替わる度にローディングが発生しています。
keepPreviousData:true
の場合
このように新しいデータの取得ができるまで、以前のデータを表示し、取得が完了すると切り替わるというような挙動になります。
さいごに
以上になります。
すごく細部までごだわっている感じがいいなあと思いました(小並感)