はじめに
Next.js 15 を使っていると、こんな記述を見かけることがあります。
"use client";
これはクライアントコンポーネントを宣言するためのディレクティブです。では、これを書かない場合は何になるのか?そもそも 2 種類のコンポーネントの何が違うのか?
本記事では、Next.js 15 におけるサーバーコンポーネントとクライアントコンポーネントの違いと使い分けについて解説します。
2種類のコンポーネント
Next.js 15 では、コンポーネントは以下の 2 種類に分かれています。
- サーバーコンポーネント(Server Component)
- クライアントコンポーネント(Client Component)
大きな違いはどこで実行されるかです。
サーバーコンポーネント
概要
サーバーコンポーネントは、サーバー側で実行されるコンポーネントです。
Next.js 15 では、"use client" の宣言がないコンポーネントはすべてサーバーコンポーネントとして扱われます。つまり、デフォルトがサーバーコンポーネントです。
特徴
- サーバー側で HTML を生成し、ブラウザに返す
- データベースや外部 API へ直接アクセスできる
- コンポーネントの JavaScript コードがブラウザに送られないため、セキュリティ面で有利
-
useState/useEffectなどの React フックは使用不可 - ボタンのクリックなどのユーザー操作を扱えない
コード例
// app/page.tsx(サーバーコンポーネント)
const Page = async () => {
// サーバー側でデータを取得する
const res = await fetch("<https://jsonplaceholder.typicode.com/posts/1>");
const post = await res.json();
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
};
export default Page;
async/await を使ったデータ取得をコンポーネント内に直接書けるのが、サーバーコンポーネントの大きな特徴です。
クライアントコンポーネント
概要
クライアントコンポーネントは、ブラウザ(クライアント)側で実行されるコンポーネントです。
ファイルの先頭に "use client" を宣言することで、そのコンポーネントはクライアントコンポーネントとして扱われます。
特徴
-
useState/useEffectなどの React フックが使用可能 - ボタンのクリックなどのユーザー操作を扱える
-
localStorageなどのブラウザ API にアクセスできる - コンポーネントの JavaScript がブラウザに送信される
コード例
// app/components/Counter.tsx(クライアントコンポーネント)
"use client";
import { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
};
export default Counter;
useState や onClick を使う場合は、必ず "use client" の宣言が必要です。宣言がないとエラーになります。
2つの違いを比較する
| サーバーコンポーネント | クライアントコンポーネント | |
|---|---|---|
| 実行場所 | サーバー | ブラウザ |
| デフォルト | ✅ | ❌("use client" が必要) |
useState / useEffect
|
❌ 使用不可 | ✅ 使用可能 |
イベントハンドラ(onClick など) |
❌ 使用不可 | ✅ 使用可能 |
| DB・API への直接アクセス | ✅ 可能 | ❌ 不可 |
ブラウザ API(localStorage など) |
❌ 使用不可 | ✅ 使用可能 |
使い分けの基本方針
コンポーネントを作る際の判断基準は以下のとおりです。
サーバーコンポーネントを選ぶケース
- データを取得して表示するだけのコンポーネント
- SEO 対策が必要なページ
- 外部 API やデータベースへのアクセスが必要な処理
クライアントコンポーネントを選ぶケース
- ボタンのクリックやフォーム入力などユーザー操作が必要
-
useState/useEffectを使う状態管理が必要 -
localStorageなどブラウザ固有の API を使う
基本的な考え方として、まずサーバーコンポーネントとして実装し、ユーザー操作や状態管理が必要になった時点でクライアントコンポーネントに切り替えるのが推奨されるアプローチです。
組み合わせて使う
実際の開発では、サーバーコンポーネントの中にクライアントコンポーネントを配置する構成が一般的です。
// app/page.tsx(サーバーコンポーネント)
import Counter from "./components/Counter"; // クライアントコンポーネント
const Page = async () => {
const res = await fetch("<https://jsonplaceholder.typicode.com/posts/1>");
const post = await res.json();
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
{/* クライアントコンポーネントを埋め込む */}
<Counter />
</div>
);
};
export default Page;
ページ全体のデータ取得はサーバーコンポーネントで行い、インタラクティブな部分のみをクライアントコンポーネントとして切り出すことで、パフォーマンスとセキュリティのバランスを保つことができます。
まとめ
- Next.js 15 ではデフォルトがサーバーコンポーネント
-
"use client"を宣言するとクライアントコンポーネントになる - サーバーコンポーネントはデータ取得・セキュリティに適している
- クライアントコンポーネントはユーザー操作・状態管理に適している
- まずサーバーコンポーネントで実装し、必要な部分だけクライアントコンポーネントにするのが基本方針
2 種類のコンポーネントを適切に使い分けることで、パフォーマンスの高いアプリケーションを構築できます。