データ取得とストリーミングの方法
このページでは、サーバーコンポーネントとクライアントコンポーネントでデータを取得する方法と、データに依存するコンポーネントをストリーミングする方法について説明します。
データの取得
サーバーコンポーネント
サーバーコンポーネントでは以下の方法でデータを取得できます:
fetch
APIを使用する- ORMまたはデータベースを使用する
fetch
APIを使用する
fetch
APIでデータを取得するには、コンポーネントを非同期関数に変更し、fetch
呼び出しをawaitします。例:
知っておくと良いこと:
fetch
のレスポンスはデフォルトではキャッシュされません。ただし、Next.jsはルートをプリレンダリングし、パフォーマンス向上のために出力をキャッシュします。動的レンダリングを選択する場合は、{ cache: 'no-store' }
オプションを使用してください。fetch
APIリファレンスを参照してください。- 開発中は、
fetch
呼び出しをログに記録して可視性とデバッグを向上させることができます。logging
APIリファレンスを参照してください。
ORMまたはデータベースを使用する
サーバーコンポーネントはサーバーでレンダリングされるため、ORMやデータベースクライアントを使用して安全にデータベースクエリを実行できます。コンポーネントを非同期関数に変更し、呼び出しをawaitします:
クライアントコンポーネント
クライアントコンポーネントでデータを取得するには2つの方法があります:
- Reactの
use
フックを使用する - SWRやReact Queryなどのコミュニティライブラリを使用する
use
フックでデータをストリーミングする
Reactのuse
フックを使用して、サーバーからクライアントへデータをストリーミングできます。まずサーバーコンポーネントでデータを取得し、Promiseをクライアントコンポーネントにpropsとして渡します:
次に、クライアントコンポーネントでuse
フックを使用してPromiseを読み取ります:
上記の例では、<Posts>
コンポーネントは<Suspense>
境界でラップされています。これはPromiseが解決される間、フォールバックが表示されることを意味します。ストリーミングについて詳しく学んでください。
コミュニティライブラリを使用する
SWRやReact Queryなどのコミュニティライブラリを使用してクライアントコンポーネントでデータを取得できます。これらのライブラリには、キャッシュ、ストリーミングなどの独自のセマンティクスがあります。例えば、SWRを使用する場合:
React.cache
でリクエストを重複排除
重複排除とは、レンダリングパス中に同じリソースに対する重複リクエストを防ぐプロセスです。これにより、異なるコンポーネントで同じデータを取得しながら、データソースへの複数のネットワークリクエストを防ぐことができます。
fetch
を使用している場合、cache: 'force-cache'
を追加することでリクエストを重複排除できます。これは同じURLとオプションで安全に呼び出し、1つのリクエストのみが行われることを意味します。
fetch
を使用せず、代わりにORMやデータベースを直接使用している場合は、データ取得をReact cache
関数でラップできます。
ストリーミング
警告: 以下の内容は、アプリケーションで
dynamicIO
configオプションが有効になっていることを前提としています。このフラグはNext.js 15 canaryで導入されました。
サーバーコンポーネントでasync/await
を使用すると、Next.jsは動的レンダリングを選択します。これはデータがサーバーで取得され、ユーザーリクエストごとにレンダリングされることを意味します。遅いデータリクエストがある場合、ルート全体のレンダリングがブロックされます。
初期読み込み時間とユーザーエクスペリエンスを向上させるために、ストリーミングを使用してページのHTMLを小さなチャンクに分割し、それらのチャンクをサーバーからクライアントに段階的に送信できます。

アプリケーションでストリーミングを実装するには2つの方法があります:
- ページを
loading.js
ファイルでラップする - コンポーネントを
<Suspense>
でラップする
loading.js
を使用する
データが取得されている間にページ全体をストリーミングするには、ページと同じフォルダにloading.js
ファイルを作成します。例えば、app/blog/page.js
をストリーミングするには、app/blog
フォルダ内にファイルを追加します。

ナビゲーション時に、ユーザーはレイアウトとローディング状態をすぐに確認でき、レンダリングが完了すると新しいコンテンツが自動的に切り替わります。

内部的には、loading.js
はlayout.js
内にネストされ、page.js
ファイルとその下の子を自動的に<Suspense>
境界でラップします。

このアプローチはルートセグメント(レイアウトとページ)に適していますが、より細かいストリーミングには<Suspense>
を使用できます。
<Suspense>
を使用する
<Suspense>
を使用すると、ページのどの部分をストリーミングするかをより細かく制御できます。例えば、<Suspense>
境界の外にあるページコンテンツをすぐに表示し、境界内のブログ投稿リストをストリーミングできます。
意味のあるローディング状態の作成
インスタントローディング状態とは、ナビゲーション後にユーザーにすぐに表示されるフォールバックUIです。最適なユーザーエクスペリエンスのために、アプリが応答していることをユーザーが理解できる意味のあるローディング状態を設計することをお勧めします。例えば、スケルトンやスピナー、将来の画面の小さくても意味のある部分(カバー写真、タイトルなど)を使用できます。
開発中は、React Devtoolsを使用してコンポーネントのローディング状態をプレビューおよび検査できます。
例
シーケンシャルなデータ取得
シーケンシャルなデータ取得は、ツリー内のネストされたコンポーネントがそれぞれ独自のデータを取得し、リクエストが重複排除されない場合に発生し、応答時間が長くなります。

一方の取得が他方の結果に依存するため、このパターンが必要な場合があります。
例えば、<Playlists>
コンポーネントは<Artist>
コンポーネントがデータの取得を終了した後にのみデータの取得を開始します。これは<Playlists>
がartistID
プロップに依存しているためです:
ユーザーエクスペリエンスを向上させるには、データが取得されている間にfallback
を表示するためにReact <Suspense>
を使用してください。これによりストリーミングが有効になり、シーケンシャルなデータリクエストによってルート全体がブロックされるのを防ぎます。
並列データ取得 (Parallel data fetching)
並列データ取得とは、ルート内のデータリクエストが積極的に開始され、同時に実行されることを指します。
デフォルトでは、レイアウトとページは並列にレンダリングされます。そのため、各セグメントは可能な限り早くデータの取得を開始します。
ただし、任意の コンポーネント内では、複数の async
/await
リクエストが連続して配置されている場合、それらは順次実行されます。例えば、以下の例では getAlbums
は getArtist
が解決されるまでブロックされます:
データを使用するコンポーネントの外側でリクエストを定義し、Promise.all
を使用して一緒に解決することで、並列にリクエストを開始できます:
補足:
Promise.all
を使用する場合、1つのリクエストが失敗すると全体の操作が失敗します。これを回避するには、代わりにPromise.allSettled
メソッドを使用できます。
データのプリロード (Preloading data)
ブロッキングリクエストの前に積極的に呼び出すユーティリティ関数を作成することで、データをプリロードできます。<Item>
は checkIsAvailable()
関数に基づいて条件付きでレンダリングされます。
checkIsAvailable()
の前に preload()
を呼び出すことで、<Item/>
のデータ依存関係を積極的に開始できます。<Item/>
がレンダリングされる時点では、そのデータはすでに取得されています。
さらに、React の cache
関数 と server-only
パッケージ を使用して、再利用可能なユーティリティ関数を作成できます。このアプローチでは、データ取得関数をキャッシュし、サーバー上でのみ実行されるようにすることができます。