React Server Componentsをわかりやすく解説
ホーム
React Server Componentsの解説
React Server Componentsの解説:use client、Server Actions、Suspense | We.Inc
React Server Components をわかりやすく解説します。境界の図解、"use client" のルール、データ取得、useActionState を使ったフォームのサーバーアクション、Suspense によるストリーミング、よくあるエラーの直し方まで。
React Server Components はサーバーでレンダリングされ、自身のJavaScriptではなく、完成したUIをブラウザーに送ります。データを直接 await したり、秘密情報をそのまま使ったりできます。インタラクティブな部分はすべて、"use client" で始まるファイルである Client Component に置きます。フォームからは "use server" を付けたサーバー関数を呼び出せ、Suspense を使えば遅い部分を後からストリーミングできます。
必要な3つのディレクティブとフック
(何も書かない) Next.js の App Router では Server Component
"use client" このファイルとそのインポート先はブラウザーでも実行される
"use server" エクスポートされた関数は、呼び出されるとサーバーで実行される
<Suspense> この部分の読み込み中は、ここにフォールバックを表示する
まずは図から見てください。青い箱はサーバーにとどまり、オレンジの箱はブラウザーにも送られます。そのうえで、データ取得、フォーム、ストリーミングのパターンをコピーし、ビルドでエラーが出たらエラー表を使ってください。
コンポーネントは、デフォルトでは Server Component のままにしておきます。 データは、表示する場所の近くにある非同期の Server Component で取得します。 "use client" は、状態やハンドラーが必要な小さな部分にだけ付けます。 フォームやデータの変更にはサーバー関数を使い、結果の表示には useActionState を使います。 遅い部分は Suspense で囲むか loading.tsx を追加して、ページがすぐに表示されるようにします。
"use client" はできるだけツリーの下のほうに置きましょう。ルートの近くに境界があると、アプリ全体が再びクライアント側になってしまいます。 サーバー関数の入力はすべて検証しましょう。自分のフォームからしか呼ばれないとしても、公開されたエンドポイントです。 ユーザーが誰なのかは、フォームを表示するページだけでなく、各サーバー関数の中でも確認しましょう。 Server Component は、インポートするのではなく children として Client Component に渡しましょう。 リクエストのウォーターフォールを避けましょう。互いに依存しない取得処理は Promise.all でまとめて開始します。
よくある質問
Server Components はサーバーサイドレンダリングと同じですか?
いいえ。サーバーサイドレンダリングは、どんなコンポーネントでも初回読み込み用にHTMLへ変換しますが、JavaScriptも送ります。Server Component は自身のJavaScriptを一切送らず、出力だけを送ります。Client Components も、初回読み込みではサーバーでレンダリングされます。
Server Components を使うには Next.js が必要ですか?
対応しているフレームワークかバンドラーが必要です。最も広く使われているのは Next.js の App Router で、Waku など、ほかにもいくつか対応しているものがあります。
Client Component から Server Component をインポートできますか?
いいえ。クライアント側のファイルからインポートすると、そのモジュールはクライアントのバンドルに含まれてしまいます。代わりに、親の Server Component から children や別の props として Server Component を渡してください。
サーバーアクションとサーバー関数の違いは何ですか?
React は現在、"use server" を付けた関数をすべてサーバー関数と呼んでいます。それがフォームの action として使われたり、トランジションの中で呼ばれたりする場合、よくサーバーアクションと呼ばれます。サーバーアクションという用語を最初に使ったのは Next.js です。
useActionState は JavaScript なしでも動きますか?
ハイドレーション前でもフォームはサーバー関数に送信されるので、送信自体はできます。保留中の状態やインラインのメッセージには JavaScript が必要なので、どちらの場合でもサーバーが役に立つページを返すようにしてください。
このモデルがWebサイトに役立つ理由
マーケティングやコンテンツのページの大部分は、見出し、テキスト、画像、商品カードなど、レンダリング後に変化しません。これらを Server Components にすればJavaScriptのコストがまったくかからず、メインスレッドが少数のインタラクティブな部分のために空くため、通常は Interaction to Next Paint が改善します。
サーバー関数のセキュリティチェックリスト
"use server" の関数はそれぞれ API ルートと同じように扱いましょう。セッションを確認し、スキーマで入力を検証し、そのユーザーがそのレコードを変更してよいかを確認し、クライアントに必要なものだけを返します。ユーザーが見るべきでないフィールドを含むデータベースの行は、決して返さないでください。
どこで何が実行されるか
それぞれが実行できる場所
やりたいこと Server Component Client Component
データベースや秘密の API キーを読む 可能 不可(秘密情報が漏れてしまう)
コンポーネント内で直接データを await する 可能(非同期コンポーネント) 不可
useState、useEffect、useReducer 不可 可能
onClick、onChange などのハンドラー 不可 可能
window、localStorage、ブラウザーの API 不可 可能(マウント後)
コンポーネントのJavaScriptを一切送らない 可能 不可
もう一方の種類をレンダリングする 可能、Client Components をレンダリングできる children や props として渡された Server Components のみ
Server Components と Client Components
データを読む Server Component
App Router では、特に指定しない限りコンポーネントは Server Components です。非同期にでき、データベースと直接やり取りできます。このコードは一切ブラウザーに届きません。
インタラクションのための Client Component
ファイルの先頭に置いた "use client" が境界を示します。このファイルと、そこからインポートされるすべてがブラウザー向けにバンドルされます。これらのファイルは小さく保ち、ツリーの末端に置きましょう。
Client Component を通して Server Component を渡す
Client Component は Server Component をインポートできませんが、children として受け取ることはできます。サーバーが先にそれをレンダリングし、クライアントは結果を配置するだけです。
秘密情報がうっかりブラウザーに漏れないようにする
server-only パッケージをインポートしておくと、クライアント側のファイルがこのモジュールをインポートした時点でビルドが失敗します。そのため、不注意なインポートから API キーが漏れることはありません。
フォームのためのサーバー関数
サーバー関数に送信するフォーム
"use server" を付けると、非同期関数がフォームから呼び出せるエンドポイントになります。本物のフォーム送信なので、JavaScriptの読み込み前でもフォームは動作します。
useActionState で保留中の状態と結果を扱う
useActionState(React 19)はサーバー関数をラップし、直前の結果と保留中フラグを返します。そのため、余分な状態を持たなくても、ボタンに「送信中」と表示したり、メッセージを表示したりできます。
変更後にページのデータを更新する
データを変更した後は、どのパスのデータが古くなったかを Next.js に伝えましょう。そうすれば次のレンダリングで変更が反映されます。
Suspense によるストリーミング
遅い部分を Suspense でストリーミングする
遅い Server Component を Suspense で囲みます。ページの残りはフォールバックを表示した状態ですぐに送られ、遅い部分はデータが届いたときにストリーミングで表示されます。
ルート全体のための loading.tsx
page.tsx の隣に loading.tsx ファイルを置くと、そのページが自動で Suspense の境界に囲まれます。そのため、ページのデータを読み込む間も、画面遷移ですぐにそれが表示されます。
リクエストをまとめて開始する
Server Component の中で取得処理を1つずつ順番に await すると、それぞれの時間が足し合わされます。まとめて開始してから、両方を await しましょう。
よく遭遇するエラー
よくあるエラーと直し方
useState などのフックは Client Component でしか動作しない "use client" のないファイルでフックを使っている インタラクティブな部分を、"use client" で始まる専用のファイルに移す
イベントハンドラーは Client Component の props に渡せない Server Component から onClick を渡している ハンドラーを Client Component の中に置くか、代わりにサーバー関数を渡す
関数を Client Components に直接渡すことはできない 通常の関数を prop として境界を越えて渡している サーバーで実行すべきなら "use server" を付け、そうでなければクライアント側のファイルで定義する
Client Components に渡せるのはプレーンなオブジェクトだけ Date を多用したモデルや Map などのクラスのインスタンスを props として送っている プレーンなデータ(文字列、数値、配列、プレーンなオブジェクト)を渡す
window is not defined サーバーでのレンダリング中にブラウザーの API を使っている useEffect の中で読み取るか、先に typeof window を確認する
ハイドレーションの不一致 サーバーとブラウザーで異なるテキスト(日付、ランダムな値)がレンダリングされた 変化する部分をクライアントでのみレンダリングするか、サーバーから値を渡す
非同期処理が初めてならこちらから:
Promise、async/await、fetch
サーバーでユーザー情報を取得 単純なマークアップ、JavaScriptは送信しない "use client":状態と onChange を持つ async:商品リストを await する 商品をカードに変換 "use client":onClick と保留中の状態 遅いクエリ、後からストリーミング
境界の図解
サーバー
クライアント
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る