🐥

React Query-基礎知識編

2022/07/31に公開

TanStack | High Quality Open-Source Software for Web Developers

React を使った Web アプリケーション開発をする際にサーバーからのデータ取得及び状態管理を行うライブラリの有力候補の一つである React Query について公式ドキュメントを読みながら自分に必要なものをまとめたメモの共有です。自分向けを他の人の役に立つかもで公開しているので文体が揃ってない部分があるのはご了承下さい。
1 記事が長いとその時必要な知識を拾いづらいのと自信のメモでも同じ単位で分割してるので以下の 4 つにわけて記事にしたいと思います。記事が作成でき次第順次リンク化していきます。

概要

Web のフロントエンドの状態を大まかに以下の 3 つに分類するとする。

  • クライアントステート
    • 複数の画面やコンポーネントで共有する状態のうちサーバーに保存不要なもの
  • サーバーステート
    • データベース等に永続化されたサーバーから取得するもの
  • ローカルステート
    • 単一のコンポーネントだけが持っているもの

React Query はこれらのステートのうちサーバーステートの管理に必要な機能を提供してくれるライブラリ。クライアントステートの管理もしようと思えば出来る作りにはなっているが、こちらは Recoil などのより特化したライブラリの方が使いやすく、どこになんの状態が入っているのかの意識わけも出来るのでその方がいいと思う。
ちなみに React Qeury という名前から fetch や axios といった HTTP クライアントのような機能も実装されてそうに思ってしまうが実際は用意されておらず、 axios 等を使ってデータを取得する関数を実装する必要がある。

初期設定

npm install @tanstack/react-query

QueryClientProvider でルートとなるコンポーネントを囲む

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

const App = () =>
  <QueryClientProvider client={queryClient}>
    <Contents />
  </QueryClientProvider>

キャッシュの仕組み

Important Defaults | TanStack Query Docs
Stale-While-Revalidate ヘッダによるブラウザキャッシュの非同期更新 | blog.jxck.io

React Query は SWR(Stale-While-Revalidate) という戦略をキャッシュ周りに採用しており、stale(古くなった) と判断される時間までは通常通りキャッシュを利用するが、stale と判断された後はキャッシュを返しつつ裏で新しいデータを取得し更新してくれる。

この動作に関するパラメータとして staleTime と cacheTime がある。

  • staleTime: キャッシュの有効期限でデフォルトは 0
    • この期限が切れたあとにデータの取得が発生すると裏で再取得が行われる
    • キャッシュがあればキャッシュを返しつつ更新後にデータが入れ替わる
  • cacheTime: キャッシュの保存期間でデフォルトは 5 minutes (5 * 60 * 1000)
    • データが参照されなくなった後にこの時間が経過するとキャッシュが削除される
    • 参照されている = データを利用しているコンポーネントがマウントされている

自動的に再取得が行われるタイミングは以下の通り。
別記事で触れる refetch や queryClient.invalidateQueries は明示的なので対象外にしている。

  • 新しい useQuery を使ったインスタンスがマウントされた
  • window からフォーカスが外れた後に再度フォーカスがあたった
  • ネットワークが切断後に再接続された
  • refetchInterval が設定されているなら指定時間経過ごと

staleTime, cacheTime のデフォルト値と refetchInterval を使用したい場合の設定方法は以下の通り。refetchInterval は自動更新間隔でデフォルトは false となっている。時間の単位は ms 。

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: Infinity,
      cacheTime: 10 * 60 * 1000, // 10 minutes
      refetchInterval: 5 * 60 * 1000, // 5 minutes
    },
  },
}

useQuery で個別に設定も可能(useQuery の詳細はデータ取得編で触れますがサーバーからのデータ取得時に使うフックです)

useQuery(key, func, {staleTime: Infinity, etc...})

Window フォーカス時の再取得

デフォルトだとアプリから離れてから再び戻ってきて window にフォーカスがあたった時にデータの再取得を行うようになっている。

デフォルトで無効化する

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
    },
  },
})

useQuery 単位で無効化する

useQuery(keys, fetchFunc, { refetchOnWindowFocus: false })

Window Focus Refetching | TanStack Query Docs
今は必要なさそうに見えたので読み飛ばしてるけどもう少しカスタマイズできそう。

Discussion