TanStack QueryのinvalidateはInfinite Queriesでどうなるのか
TanStack Query
TanStack Queryはキャッシュ機構を内包してサーバー状態の管理を便利にするライブラリです。
データを取得(同期)する場合はqueriesを、データを更新する場合はmutationsと呼ばれる機構を利用します。
Infinite Queries
Infinite QueriesはTanStack Queryの機能のひとつで、「無限スクロール」と呼ばれるような追加読み込みの機能を提供します。利用する際は、追加ページがあるかどうかを示すパラメタ(pageParams)を指定するだけで、ページ単位のデータが取得できるようになります。
Optimistic Updates
データの更新処理において、Optimistic Updates(楽観的更新)と呼ばれる手法があります。サーバーへの更新依頼と同時に手元のキャッシュデータを成功状態に更新しておき、エラーがあった場合にはもとに戻す、という手法です。通信をまたずに変更がUIに適用されるので、ユーザー体験が良くなることがあります。
TanStack Queryでもそのやり方が提供されています。
- mutationのonMutateでキャッシュを更新
- onErrorで状態をもとに戻す
- onSettled (成功/失敗ともに) でバックグラウンドでキャッシュを更新 (invalidate)
const queryClient = useQueryClient()
useMutation({
mutationFn: updateTodo,
// When mutate is called:
onMutate: async (newTodo) => {
// Cancel any outgoing refetches
// (so they don't overwrite our optimistic update)
await queryClient.cancelQueries({ queryKey: ['todos'] })
// Snapshot the previous value
const previousTodos = queryClient.getQueryData(['todos'])
// Optimistically update to the new value
queryClient.setQueryData(['todos'], (old) => [...old, newTodo])
// Return a context object with the snapshotted value
return { previousTodos }
},
// If the mutation fails,
// use the context returned from onMutate to roll back
onError: (err, newTodo, context) => {
queryClient.setQueryData(['todos'], context.previousTodos)
},
// Always refetch after error or success:
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] })
},
})
本題
onSettledでのinvalidateでは、queryKeyを指定することでリフレッシュする対象となるキャッシュを指示しています。一方でInfinite Queriesの場合、ひとつのqueryKeyに対して複数ページの情報がひも付きます。
たとえば10ページ目まで読み込んだ状態で更新処理を実行したらinvalidateの処理はどうなるのでしょう。
答えは「1ページ目から順に読み込まれる」です。
全ページ分が一度にfetchされたらまずい、と思い検証してみました。
2ページ分読み込んだ状態で更新(Add Todo)した動画が以下になります。
まとめ
公式ドキュメントにがっつり書いてありました。
以上、ちゃんとドキュメント読みましょう案件でした。
Discussion