🔄

TanStack QueryのinvalidateはInfinite Queriesでどうなるのか

2024/11/12に公開

TanStack Query

TanStack Queryはキャッシュ機構を内包してサーバー状態の管理を便利にするライブラリです。
データを取得(同期)する場合はqueriesを、データを更新する場合はmutationsと呼ばれる機構を利用します。
https://tanstack.com/query/latest

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'] })
  },
})

https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates#optimistic-updates

本題

onSettledでのinvalidateでは、queryKeyを指定することでリフレッシュする対象となるキャッシュを指示しています。一方でInfinite Queriesの場合、ひとつのqueryKeyに対して複数ページの情報がひも付きます。
たとえば10ページ目まで読み込んだ状態で更新処理を実行したらinvalidateの処理はどうなるのでしょう。
答えは「1ページ目から順に読み込まれる」です。
全ページ分が一度にfetchされたらまずい、と思い検証してみました。

2ページ分読み込んだ状態で更新(Add Todo)した動画が以下になります。

https://github.com/MtBlue81/react-query-invalidate

まとめ

公式ドキュメントにがっつり書いてありました。

https://tanstack.com/query/latest/docs/framework/react/guides/infinite-queries#what-happens-when-an-infinite-query-needs-to-be-refetched

以上、ちゃんとドキュメント読みましょう案件でした。

Discussion