10
チャプター10
サーバーコンポーネントとクライアントコンポーネント
サーバーコンポーネントとクライアントコンポーネントがどのように機能するかを理解するために、2つの基本的なウェブの概念に慣れておくと役立ちます
サーバーとクライアントの環境
ウェブアプリケーションのコンテキストにおいて

- クライアントとは、ユーザーのデバイス上のブラウザを指し、アプリケーションコードのためにサーバーにリクエストを送信します。その後、サーバーから受け取った応答を、ユーザーが操作できるインターフェースに変換します。
- サーバーとは、データセンターにあるコンピュータを指し、アプリケーションコードを保存し、クライアントからのリクエストを受け取り、何らかの計算を行い、適切な応答を返します。
各環境には、それぞれ独自の機能と制約があります。たとえば、レンダリングとデータ取得をサーバーに移動することで、クライアントに送信されるコードの量を減らし、アプリケーションのパフォーマンスを向上させることができます。しかし、以前に学んだように、UIをインタラクティブにするには、クライアントでDOMを更新する必要があります。
したがって、サーバーとクライアントのために書くコードは常に同じではありません。特定の操作(例:データ取得やユーザー状態の管理)は、どちらか一方の環境により適しています。
ネットワーク境界
ネットワーク境界は、異なる環境を分離する概念的な線です。
Reactでは、コンポーネントツリー内のどこにネットワーク境界を配置するかを選択します。たとえば、サーバーでデータを取得してユーザーの投稿をレンダリングし(サーバーコンポーネントを使用)、その後、各投稿のインタラクティブなLikeButton
をクライアントでレンダリングできます(クライアントコンポーネントを使用)。
同様に、サーバーでレンダリングされ、ページ間で共有されるNav
コンポーネントを作成できますが、リンクのアクティブ状態を表示したい場合は、Links
のリストをクライアントでレンダリングできます。

舞台裏では、コンポーネントは2つのモジュールグラフに分割されます。サーバーモジュールグラフ(またはツリー)には、サーバーでレンダリングされるすべてのサーバーコンポーネントが含まれ、クライアントモジュールグラフ(またはツリー)には、すべてのクライアントコンポーネントが含まれます。
サーバーコンポーネントがレンダリングされた後、React Server Component Payload (RSC)と呼ばれる特殊なデータ形式がクライアントに送信されます。RSCペイロードには以下が含まれます。
- サーバーコンポーネントのレンダリング結果。
- クライアントコンポーネントがレンダリングされるべき場所のプレースホルダー(または穴)と、それらのJavaScriptファイルへの参照。
Reactはこの情報を使用して、サーバーコンポーネントとクライアントコンポーネントを統合し、クライアントでDOMを更新します。
これがどのように機能するか見てみましょう。
クライアントコンポーネントの使用
前のチャプターで学んだように、Next.jsはデフォルトでサーバーコンポーネントを使用します。これはアプリケーションのパフォーマンスを向上させるためであり、それらを採用するために追加の手順を踏む必要がないことを意味します。
ブラウザのエラーを振り返ると、Next.jsはサーバーコンポーネント内でuseState
を使用しようとしていることを警告しています。インタラクティブな「いいね」ボタンをクライアントコンポーネントに移動することで、この問題を解決できます。
app
フォルダー内にlike-button.js
という新しいファイルを作成し、LikeButton
コンポーネントをエクスポートします
export default function LikeButton() {}
<button>
要素とhandleClick()
関数をpage.js
から新しいLikeButton
コンポーネントに移動します
export default function LikeButton() {
function handleClick() {
setLikes(likes + 1);
}
return <button onClick={handleClick}>Like ({likes})</button>;
}
次に、likes
の状態とインポートを移動します
import { useState } from 'react';
export default function LikeButton() {
const [likes, setLikes] = useState(0);
function handleClick() {
setLikes(likes + 1);
}
return <button onClick={handleClick}>Like ({likes})</button>;
}
さて、LikeButton
をクライアントコンポーネントにするには、ファイルの先頭にReactの'use client'
ディレクティブを追加します。これは、コンポーネントをクライアントでレンダリングするようにReactに指示します。
'use client';
import { useState } from 'react';
export default function LikeButton() {
const [likes, setLikes] = useState(0);
function handleClick() {
setLikes(likes + 1);
}
return <button onClick={handleClick}>Like ({likes})</button>;
}
page.js
ファイルに戻り、LikeButton
コンポーネントをページにインポートします
import LikeButton from './like-button';
function Header({ title }) {
return <h1>{title ? title : 'Default title'}</h1>;
}
export default function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
return (
<div>
<Header title="Develop. Preview. Ship." />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<LikeButton />
</div>
);
}
両方のファイルを保存し、ブラウザでアプリを表示します。エラーがなくなると、変更を加えて保存するたびに、ブラウザが自動的に更新されて変更が反映されることに気づくでしょう。
この機能はFast Refreshと呼ばれています。これは、行った編集に対して即座にフィードバックを提供し、Next.jsにプリセットで含まれています。
まとめ
要約すると、サーバーとクライアントの環境、そしてそれぞれをいつ使用するかについて学びました。また、Next.jsがデフォルトでReactサーバーコンポーネントを使用してパフォーマンスを向上させていること、そしてUIのごく一部をインタラクティブにするためにクライアントコンポーネントをどのように選択できるかについても学びました。
補足資料
サーバーコンポーネントとクライアントコンポーネントについては、さらに多くのことを学ぶことができます。追加のリソースを以下に示します。
この情報は役立ちましたか?