Open4

自分内 SWR vs React Query のメモ

よしこよしこ

SWR と React Query どっち使ってるの

2021年12月の現状として、ついこの間まではSWRを使っていたが、最近React Queryに乗り換えた。
両方触ってみた感じ、たしかにReact Queryのほうが多機能(そのぶんバンドルサイズもデカいけど)

ただ解決したい課題と解決手法は同じなので、APIはほとんど一緒。
腐敗防止層になる中継ファイルを作り、適切にAPIやOptionsを中継しておけば、乗り換えはそのファイル内の書き換えのみで済む。

機能比較ページ: https://react-query.tanstack.com/comparison

よしこよしこ

React Queryの優位性(2021/12現在)

キャッシュを参照しないオプション

乗り換えに至った直接的な理由。
あるリソース詳細を取得済みだったとしても、そのリソースの編集フォームではそのキャッシュを使いたくない。
なぜなら、最初にキャッシュが渡ってくるとFormがそれを元にStateを生成してしまい、あとから最新の値が渡ってきても上書きすることができず古いデータから編集が始まってしまうから。(上書きしてしまうとタイミングによっては入力中の値が消えうる)

これをReact QueryではoptionのstaleTimeを0にすることで実現できる。

SWRには同等の機能がなく、 https://github.com/vercel/swr/discussions/456 で議論されている。
対応するPRは https://github.com/vercel/swr/issues/1705 とのこと。

Keyの前方一致

React QueryではKeyに配列を使ったとき、前方一致で複数のKeyを無効化することができる。
['a', 'b']'['a', 'c'] というKeyのキャッシュがあったとき、 queryClient.invalidateQueries(['a']) で両方を無効化できる。
これを使うと、

  • ページングのある一覧に対してリソースが変更されたときすべてのページのキャッシュを無効化する
    • これはSWR/React Query双方にあるページングのAPI使うのが正しいかも
  • 親子関係のあるリソースに対して親に変更があったら親と親に含まれる子のキャッシュをすべて無効化する(子のキャッシュのKeyを [親ID, 子ID] としておけばよい)

などができて便利。

よしこよしこ

SWRの追随

とはいえSWRもReact Queryのいいところを随時吸収していっている印象がある。
Keyの配列対応やKey ObjectのDeep Compare / Serializationなど。
上に書いたKey配列の前方一致も今後Optionで入ってきそうな気がする。
1.2で入った楽観更新のロールバックサポートも注目している。

よしこよしこ

注目している差異

Suspenseモードでの並列取得のAPI

Suspenseモードだと、取得を単純に上下に並べて書くと先のfetchでSuspenseされてしまって直列取得になってしまう。

React Queryでの回避策としてはuseQueriesが推奨されている( https://react-query.tanstack.com/guides/parallel-queries の注意書きに書いてある)。
ただ、使うhooksごと変わってしまうため、useQuery込みで抽象化していた場合に手が出しづらい。

SWRにはまだ回避策がなく、 https://github.com/vercel/swr/pull/168 で議論中なので、どう着地するのか注目している。
冒頭のdescriptionにあるようにuseSWRはそのままで、それをさらにラップする形のAPIになってくれたら嬉しい。