ガイドこのページを編集.md

クライアントコンポーネント

クライアントサイドとインタラクティブにやり取りしたい場合、クライアントコンポーネントを使用できます。クライアントコンポーネントもサーバー側でレンダリングされますが、クライアント側でハイドレーションされます。

クライアントコンポーネントはすべて非同期に読み込まれるため、ページのレンダリングを妨げることはありません。すべてESモジュールにコンパイルされ、必要な時だけ読み込まれます。

クライアントコンポーネントを作成するには、ファイルの冒頭に"use client";を追記してください。

"use client"; export default function MyClientComponent() { return <p>This is a client component</p>; }

クライアントコンポーネントはすべてのReactフックで使用可能です。例えば、useStateフックやonClickのようなイベントハンドラとも併用できます。クライアントコンポーネントはサーバー側とクライアント側の両方でレンダリングされます。

"use client"; import { useState } from "react"; export default function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

クライアントコンポーネントはサーバーコンポーネントからpropsを受け取ることができます。propsはシリアル化された状態でクライアント側に受け渡されます。クライアント側に受け渡す全てのpropsはシリアル化可能なものでなければいけません。propsとして基本的な値、配列、オブジェクトを渡すことができますが、関数を渡すことはできません。

"use client"; export default function MyClientComponent({ name }) { return <p>Hello {name}</p>; }

上記のクライアント・コンポーネントをサーバー・コンポーネントから使用する:

import MyClientComponent from "./MyClientComponent"; export default function MyServerComponent() { return <MyClientComponent name="John" />; }

サーバーコンポーネントをクライアントコンポーネントでラップすることもできます。React Contextプロバイダーのように、クライアントコンポーネント内でサーバーコンポーネントを使いたいときに非常に便利です。このコンテキストはすべての子コンポーネントで利用できます。コンテキストはクライアント側でのみ作成されるので、サーバーコンポーネントからはアクセスできません。

"use client"; import { createContext } from "react"; const MyContext = createContext("unknown"); export default function MyProvider({ name, children }) { return <MyContext.Provider value={name}>{children}</MyContext.Provider>; }
import MyProvider from "./MyProvider"; export default async function MyServerComponent() { const name = await getUserName(); return ( <MyProvider name={name}> <p>Hello {name}</p> </MyProvider> ); }

クライアントコンポーネントごとに別ファイルを作成する代わりに、関数本体の中で"use client"ディレクティブを使用できます。これにより、使用するサーバーコンポーネントのすぐ隣にクライアントコンポーネントをインラインで定義できます。

import { useState } from "react"; function Counter() { "use client"; const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default function App() { return ( <div> <h1>My App</h1> <Counter /> </div> ); }

上記のCounter関数は自動的に別のクライアントコンポーネントモジュールとして抽出されます。サーバーコンポーネントAppは関数そのものではなく、Counterへのクライアント参照をレンダリングします。

他の関数内でもインラインクライアントコンポーネントを使用できます。フレームワークは親スコープからキャプチャされた変数を自動的に検出し、抽出されたクライアントコンポーネントにpropsとして渡します。

import { useState } from "react"; export default function App() { const label = "clicks"; const Counter = () => { "use client"; const [count, setCount] = useState(0); return ( <div> <p>{label}: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; return ( <div> <h1>My App</h1> <Counter /> </div> ); }

この例では、label変数がAppのスコープからキャプチャされ、クライアントコンポーネントにpropsとして自動的に転送されます。インラインコンポーネントが使用するモジュールレベルのインポートやトップレベルの宣言は、抽出されたモジュールに直接含まれます。

注意: キャプチャされた変数はすべて、通常のクライアントコンポーネントのpropsと同様にシリアル化可能でなければなりません。関数、クラスインスタンス、その他のシリアル化できない値はキャプチャできません。

ClientOnlyコンポーネントでコンポーネントをラップすることで、クライアント専用のコンポーネントを作成できます。ClientOnly コンポーネントの子コンポーネントは、クライアント側でのみレンダリングされます。

import { ClientOnly } from "@lazarv/react-server/client"; export default function MyServerComponent() { return ( <div> <p>This is rendered on the server side</p> <ClientOnly> <p>This is rendered on the client side</p> <MyClientComponent /> </ClientOnly> </div> ); }