サーバー/クライアントコンポーネントを理解する
Next.js App Routerでは、すべてのコンポーネントはデフォルトでサーバーコンポーネントです。 しかし、時にはクライアント側の機能(例:useState、onClickなど)が必要な場合があります。このような場合はどうすればよいでしょうか?
クライアントコンポーネントを使用するには、ファイルの先頭に'use client'ディレクティブを追加します。
'use client'
export const ClientComponent = () => {
 return (
   <div>
     <h1>Client Component</h1>
   </div>
 );
};これにより、そのコンポーネントからクライアント境界(Client Boundary)が形成され、コンポーネントでインポートされるすべてのコンポーネントおよびモジュールファイルはクライアント側で動作します。 (ここで重要なのは、コンポーネントのレンダリング階層構造ではなく、インポート関係です。)
そのため、'use client'を付けていないコンポーネントも自動的にクライアントコンポーネントに変換されます。
このような場合はどうでしょうか?クライアントコンポーネント内にサーバーコンポーネントを宣言してみましょう。
import React from 'react';
export const ServerComponent = async () => {
  const data = await getData();
  return <div>{JSON.stringify(data)}</div>;
};
async function getData() {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
  const json = await res.json();
  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }
  return json;
}
export default ServerComponent;'use client'
import ServerComponent from './ServerComponent'
export const ClientComponent = () => {
  return (
    <div>
      <h1>Client Component</h1>
      <ServerComponent />
    </div>
  )
}次のような警告とともにエラーログが表示されます:

クライアントコンポーネントとサーバーコンポーネントを一緒に使用する際には、以下のような重要なルールがあります:
- ✅ サーバーコンポーネントの下にクライアントコンポーネント(可能)
- ✅ クライアントコンポーネントの下にクライアントコンポーネント(可能)
- ❌ クライアントコンポーネントの下にサーバーコンポーネント(不可能)
🔧 解決策:Propsパターンの活用
では、クライアントコンポーネント内でサーバーコンポーネントを使用するにはどうすればよいでしょうか?答えは簡単です:propsとして渡します。
// 動作するパターン
'use client'
export const ClientComponent = ({ children }) => {
  return (
    <div>
      <h1>Client Component</h1>
      {children}
    </div>
  );
};
const App = () => {
  return (
    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
  )
}なぜこのように動作するのか?
鍵となるのは、Client Boundaryがコンポーネントの親子関係ではなく、インポート位置を基準に決定されるという点です。
上記の例では、ServerComponentはサーバーコンポーネントであるAppからインポートされているため、サーバーコンポーネントとして維持されます。
ClientComponentは単にpropsとして受け取ったchildrenがどこでレンダリングされるかを知っているだけで、どのようなコンポーネントが来るかは知りません。
このパターンにより、Layoutにuse clientで宣言されたProviderなどで包まれていても、サーバーコンポーネントを使用することができます。
詳細な解説
サーバーコンポーネントは、従来のサーバーサイドレンダリング(SSR)とは全く異なる方法で動作します。
SSRがサーバーで完成したHTMLを生成するのに対し、サーバーコンポーネントはReact Server Components(RSC)Payloadと呼ばれる特別な形式のJSON-likeストリームを生成します。

このRSC Payloadには、コンポーネントツリー構造、データ、HTMLコンテンツなどが含まれており、サーバーでは文字列、数値、配列などの基本的なデータ型とReactエレメント、Dateオブジェクト、Map、Setなどの組み込みオブジェクトをシリアライズしてこのペイロードに含めます。 一方、関数、クラスインスタンス、クロージャ、イベントリスナーなどはシリアライズできません。
したがって、サーバーコンポーネントからクライアントコンポーネントにシリアライズできない値をpropsとして渡すことはできません!
サーバーコンポーネントをレンダリングする過程でクライアントコンポーネントに遭遇すると、その部分は特別なプレースホルダーでマークされます。 このプレースホルダーにはクライアントコンポーネントの参照とprops情報が含まれており、クライアントで該当コンポーネントを正確にレンダリングできるようになっています。
クライアントはサーバーから受け取ったRSCペイロードをReactが理解できる形式に変換し、サーバーから受け取ったコンテンツをハイドレーションします。 このとき、プレースホルダーでマークされた部分には該当するクライアントコンポーネントがレンダリングされます。
参照

 によって翻訳されました。誤訳があれば教えてください!
によって翻訳されました。誤訳があれば教えてください!