ReactとNext.jsのデータ取得を1つのアプリで比較
Reactのデータ取得:サーバー、TanStack Query、SWR | We.Inc
短いクイズでReactのデータ取得方法を選び、サーバーコンポーネント、TanStack Query、SWRをキャッシュ、更新処理、デフォルト動作の観点から1つのサンプルアプリで比較します。
可能ならサーバーで取得しましょう。Next.jsのApp Routerでは、asyncのサーバーコンポーネントがHTMLを送る前にデータをawaitするため、ローディングスピナーのコードは不要です。ページを開いている間に変化するデータには、TanStack QueryやSWRなどのクライアントキャッシュを使います。これらはキャッシュ、リトライ、更新処理を扱ってくれます。単発のリクエストなら素のuseEffectでのfetchで十分です。
どの方法が合うか
- asyncサーバーコンポーネント
- サーバー
- デフォルトではキャッシュなし、use cacheで有効化
- ページのデータ、シークレット、データベースクエリ
- TanStack Query
- ブラウザー
- queryKeyをキーとするクエリキャッシュ
- ダッシュボード、更新処理、ページング
- SWR
- ブラウザー
- リクエストキーをキーとするキャッシュ
- 常に最新であるべき読み取り中心の画面
- useEffect + fetch
- ブラウザー
- 自分で書かない限りなし
- 小さなアプリでの小さなリクエスト1つ
このページのすべての例は、同じ小さなメモ一覧を読み込み、編集します。そのため、違いはデモではなく方法そのものから生まれます。下の3つの質問に答えると、最初のおすすめとそれに合ったスニペットが表示されます。
- Next.jsのApp Routerのような、サーバーコンポーネントを持つフレームワークを使っているかを答えます。
- ページを開いている間にデータを最新に保つ必要があるか、ユーザーがデータを編集するかを答えます。
- おすすめを読み、対応するスニペットをコピーします。
- 公開前に、下の比較セクションでデフォルト動作を確認します。
- リクエストは同時に開始しましょう。awaitを2つ続けるとウォーターフォールになります。先に両方のPromiseを作成し、Promise.allでawaitします。
- 同じデータを読むすべてのuseQueryに同じqueryKeyを付けると、コンポーネント間で1つのリクエストと1つのキャッシュエントリーを共有できます。
- 更新処理の後は、即時の楽観的更新が必要でない限り、キャッシュを手作業で書き換えるのではなく、影響を受けるキーを無効化しましょう。
- クライアントコンポーネントでシークレットを取得してはいけません。ブラウザーがリクエストしたものは、ネットワークパネルで誰でも見られます。
よくある質問
Next.jsのApp Routerではfetchリクエストはキャッシュされますか?
現在のNext.jsのドキュメントによると、fetchリクエストはデフォルトではキャッシュされず、完了するまでレンダリングをブロックします。1回のレンダリング内の同一リクエストはメモ化され、キャッシュはuse cacheディレクティブで有効にするか、Suspense内で最新データをストリーミングします。
TanStack Queryの重要なデフォルト設定は何ですか?
データはすぐにstaleになる(staleTimeは0)ため、マウント時、ウィンドウのフォーカス時、再接続時に再取得されます。使われていないクエリは5分間メモリに残り(gcTime)、失敗したクエリは指数バックオフで3回リトライされます。再取得が多すぎる場合はstaleTimeを大きくしましょう。
TanStack QueryとSWRのどちらを選ぶべきですか?
どちらもキーでキャッシュし、フォーカス時と再接続時に再検証します。TanStack Queryは更新処理、無効化、devtoolsの組み込み機能が豊富で、SWRはuseSWR(key, fetcher)を中心とした小さなAPIです。アプリごとにどちらか1つを選びましょう。両方使うとキャッシュが重複します。
サーバーコンポーネントがあってもクライアントライブラリは必要ですか?
ページの読み込みだけなら不要なことが多いです。ページ遷移なしでデータを更新する必要がある場合、ユーザーが編集して即座の反応を期待する場合、無限リストの場合には必要になります。多くのアプリはサーバーで読み込み、インタラクティブな画面でのみクライアントキャッシュを使います。
サーバー上でSupabaseのログインユーザーをどう確認すべきですか?
Supabaseのサーバーサイドガイドでは、サーバーコード内でgetSession()を信頼してはいけないとしています。トークンの署名を検証するsupabase.auth.getClaims()を呼び出してから、テーブルにクエリを実行します。行レベルセキュリティはすべてのクエリに引き続き適用されます。
まずサーバー、必要な場所にクライアントキャッシュを追加
- サーバーコンポーネントは、認証情報を使ってデータベースに直接クエリを実行したりAPIを呼び出したりでき、結果はHTMLとして届きます。これにより、ほとんどのページからローディング状態のコードがなくなり、キーがブラウザーのバンドルに含まれることもありません。
- インタラクティブな画面は事情が異なります。追加、絞り込み、再訪問が行われるメモ一覧では、画面間で結果を記憶してバックグラウンドで更新するクライアントキャッシュが役立ちます。
待つ代わりにストリーミング
- 遅いリクエストが1つある場合は、それを必要とするコンポーネントをfallback付きのSuspenseで囲みます。ページの残りはすぐに送信され、遅い部分は後からストリーミングされます。Next.jsではloading.jsファイルがルートセグメント全体に対して同じことを行います。
- クライアントコンポーネントでは、サーバーからPromiseを受け取り、Suspense内でReactのuse APIを使って読み取ることもできます。
素のuseEffectパターンが不十分な理由
- useEffect内のfetchにはキャッシュがないため、マウントのたびにリクエストが繰り返され、競合状態、ローディング、エラーを手作業で処理する必要があります。小さなウィジェット1つなら問題ありません。それより大きなものでは、ライブラリを使えば数行でそのすべてが手に入ります。fetch自体の基本は、asyncとfetchのガイドで解説しています。
意外なデフォルト動作
初期状態での動作
- 動作
- Next.jsのサーバーfetch
- TanStack Query
- SWR
- リクエストをまたいだキャッシュ
- なし、use cacheで有効化
- メモリ内、ブラウザーのタブごと
- メモリ内、ブラウザーのタブごと
- 重複リクエスト
- 1回のレンダリング内でメモ化
- queryKeyで共有
- 2秒以内はキーで重複排除
- ウィンドウのフォーカス時に再取得
- 該当なし
- あり、staleの場合
- あり
- 再接続時に再取得
- 該当なし
- あり、staleの場合
- あり
- 失敗時のリトライ
- 自分で処理する
- 3回、指数バックオフ
- あり(errorRetryInterval 5000 ms)
- 未使用データの保持期間
- 該当なし
- 5分(gcTime)
- ドキュメント化されたデフォルトなし
サーバーでのウォーターフォールを避ける
両方のリクエストを開始してから、まとめてawaitする
awaitする前に両方の関数を呼び出すので、どちらも相手を待ちません。
遅い部分をSuspenseでストリーミング
見出しはすぐに送信され、メモ一覧はデータが届いた時点でストリーミングされます。
サーバーコンポーネントでのSupabase
ここでは、SupabaseのNext.jsサーバーサイドガイドにあるcreateClientヘルパー(lib/supabase/server.ts、@supabase/ssrベース)を使います。getClaims()がクエリ実行前にログインユーザーのトークンを検証します。
ログインユーザーのメモをサーバーで読み込む
notesテーブルの行レベルセキュリティが、どの行を返すかを決めます。
方法を選ぶ
サーバーコンポーネント(例:Next.jsのApp Router)を使っていますか?
ページを開いたままの間にデータを更新する必要がありますか?
ユーザーは画面上でこのデータを編集しますか?
はい
いいえ
スタート用スニペット
スニペットをコピー
asyncサーバーコンポーネントで読み込みましょう。クライアントキャッシュは、後でインタラクティブになる部分にだけ追加します。
TanStack Queryを使いましょう:読み取りにはuseQuery、書き込みにはuseMutation、変更後の更新にはinvalidateQueriesを使います。
SWRを使いましょう:useSWRはごくわずかなコードで、フォーカス時と再接続時に画面を最新に保ちます。
ここでは単一のuseEffectでのfetchで十分です。遅れて届いたレスポンスが新しい状態を上書きしないよう、ignoreフラグでクリーンアップしましょう。
おすすめ:{v}
サーバーコンポーネント
TanStack Query
SWR
useEffectとfetch
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る