Slide 1

Slide 1 text

React Query 導入と 実装ルールについて考える 2022.11.26 JSConf JP 2022 | 株式会社カオナビ Yuuki Minami © kaonavi, inc.

Slide 2

Slide 2 text

© kaonavi, inc. 2 ● Yuuki Minami ● CTO 室 フロントエンド支援チーム ● 🍜🍺❤

Slide 3

Slide 3 text

React Query の導入時に得られた知見や 実装について考えたこと 話すこと © kaonavi, inc. 3

Slide 4

Slide 4 text

INDEX 1 .React Query について 2 .React Query 導入と選定 3 .実装ルール・実装例 4 .React Query の近時 © kaonavi, inc. 4 5 .まとめ

Slide 5

Slide 5 text

React Query について © kaonavi, inc. 5

Slide 6

Slide 6 text

React Query (TanStack Query) © kaonavi, inc. 6 ● 非同期状態管理ライブラリ ○ データ取得 ○ サーバーデータ (API レスポンス) のキャッシュ ● v4 から TanStack Query へ名称変更 ○ React, Solid, Vue に対応 (2022年11月時点)

Slide 7

Slide 7 text

React Query の特徴 © kaonavi, inc. 7 ● stale-while-revalidate キャッシュ戦略 ● 同一データ取得リクエストの重複削除 ● garbage collection の設定 ● structural sharing による Query 結果のメモ化 ● バックグラウンドでのデータ更新 ● Suspense モード

Slide 8

Slide 8 text

useQuery Component がレンダリングされるとキャッシュが有効であれ ばキャッシュされたデータを返し、キャッシュが存在しない場 合やキャッシュの状態が Stale の時はデータをフェッチする。 ● queryKey: キャッシュ管理のための 一意なキー ● queryFn: データ取得のための Promise を返す関数 基本的な使い方 © kaonavi, inc. 8

Slide 9

Slide 9 text

React Query 導入と選定 © kaonavi, inc. 9

Slide 10

Slide 10 text

● 一部のページで MPA -> SPA へ移行 ● 歴史的背景 ○ Redux Store がページ毎に存在 (Not single store) ● SPA で Redux 以外の Global State 共有のアプローチが必要 ● SPA 化によりキャッシュ活用の機運が高まる ● Redux 実装が肥大化しがちでつらい 導入のモチベーション © kaonavi, inc. 10

Slide 11

Slide 11 text

● React Query ○ 自動 garbage collection 👍 ○ 公式 Devtools 👍 ○ 開発の勢いとリリースサイクルの早さ 👍 ● SWR ○ シンプル・必要最低限の機能はある ○ サイズが小さい ● RTK Query ○ 歴史的背景から Redux (RTK) がシングルストアではない ○ Redux にロックイン 他の候補との比較と導入の決め手 © kaonavi, inc. 11

Slide 12

Slide 12 text

Stale Time ● Query を fresh から stale へ移行す るまでの時間 ● fresh の間はデータは常にキャッシュ から取得され、リクエストが走ることは ない ● stale の場合、キャッシュを返しつつ バックグラウンドで再取得とデータ更 新が可能 React Query Concepts © kaonavi, inc. 12 ● 非アクティブな Query のキャッシュを 削除 (GC) するまでの時間 ● Observer (その Query を利用するコ ンポーネント) が全て unmount される と Query は非アクティブに移行 Cache Time © kaonavi, inc. 12

Slide 13

Slide 13 text

React Query Devtools ● Query 毎にキャッシュされているデータが確 認可能 ● Query の状態が把握でき、ボタンからデータ の再取得やキャッシュの破棄も可能 ● オプトインなので利用する際は本体と別にイ ンストール ● development build でのみ有効化される

Slide 14

Slide 14 text

TanStack/query 開発とリリース © kaonavi, inc. 14 https://github.com/TanStack/query/pulse/monthly © kaonavi, inc. 14

Slide 15

Slide 15 text

TanStack/query 開発とリリース https://www.npmjs.com/package/@tanstack/react-query?activeTab=versions © kaonavi, inc. ● Opened issues: 18 (資料作成時点) ● Feature Requests & Questions は Discussions ● Issue の修正が早い ● リリース頻度が高い ので修正がマージされたらす ぐに取り込める 15

Slide 16

Slide 16 text

Comparison Matrix © kaonavi, inc. 16 https://tanstack.com/query/v4/docs/comparison

Slide 17

Slide 17 text

Redux は不要になるか? © kaonavi, inc. 17 ● API レスポンス以外の Global State を React Context 等に寄せることで場合によっては不要 ○ Context でレンダリングを最適化するには Context を適宜分割し、複数の Provider を用意 する必要がある ● 複雑な要件に対応させるために API レスポンス以外にも様々な Global State を管理 ● レンダリング最適化や可読性の観点から、 Redux は引き続き有用と考える

Slide 18

Slide 18 text

実装ルール・実装例 © kaonavi, inc. 18

Slide 19

Slide 19 text

Custom Hooks © kaonavi, inc. 19 ● Query 毎に Custom Hooks で抽象化し、可搬性・ 保守性の向上 ● Component から直接 useQuery を呼ばない ● コアメンテナ Dominik 氏のブログでも推奨 ○ https://tkdodo.eu/blog/practical-react-query ※v5では useQuery の引数は単一のオブジェクトのみ許容に

Slide 20

Slide 20 text

Query Keys © kaonavi, inc. 20 ● 一意性を担保するためにルールを設定 ● common or features ○ common: 省略 ○ features: feature 名を含める ● Hooks name ○ useFoo の foo を含める ● Custom Hooks ファイル内で定義 ○ 利用する Query Keys を間違えない ○ コンフリクトしない

Slide 21

Slide 21 text

useQuery options type ● useQuery に options を渡すことが可能 ● Custom Hooks の引数で options を受け取る ● select option による取得データの加工 ○ select で取得されるデータに変更があっ た場合のみ再レンダリング ○ 型推論させるために工夫が必要 ○ 最適解求む! © kaonavi, inc. 21

Slide 22

Slide 22 text

React Query の近時 © kaonavi, inc. 22

Slide 23

Slide 23 text

ESLint Plugin © kaonavi, inc. 23 ● v4.14.0で追加 ● @tanstack/query/exhaustive-deps ○ queryFn 内で利用するパラメータは queryKey に指 定する ● @tanstack/query/prefer-query-object-syntax ○ useQuery の引数は単一のオブジェクトのみ許容

Slide 24

Slide 24 text

suspense for useQueries © kaonavi, inc. 24 ● v4.15.0で useQueries が suspense モードに対 応 (experimental とのこと) ● 全ての Query の取得が完了するまでコンポー ネントツリーはマウントせずに fallback ● Issue が報告されてから約 2年越しに解決 🎉 ● 通常の useQuery の suspense モードでは ウォーターフォール的にしか実行できない

Slide 25

Slide 25 text

● useQuery の引数は単一のオブジェクトのみ許容 ● require React >=18.2.0 ● require TypeScript >=4.7 ● rename cacheTime to gcTime ● rename useErrorBoundary to throwError ● Optional chaining のトランスパイル廃止によるバンドルサイズ改善 v5 Roadmap © kaonavi, inc. 25 現在ドラフト https://github.com/TanStack/query/discussions/4252

Slide 26

Slide 26 text

まとめ © kaonavi, inc. 26

Slide 27

Slide 27 text

まとめ © kaonavi, inc. 27 ● React Query はプロダクトで活躍できるポテンシャルがある ○ 痒いところに手が届く API や Options ○ Devtools や ESLint Plugin による開発者体験 ○ 開発の勢い ● 実装のルールはしっかり考えないと破綻する可能性あり (特に Query Keys) ● Stale Time と Cache Time の概念だけ最初は少々戸惑いがち ○ 実際に手元で動かして理解するのが一番 ● 開発が早く、検索した情報が古くなっている可能性があるので公式ドキュメントと照らし合 わせる