Server / Client Components
なぜ学ぶか: Next.jsのコードで一番大事な概念がこれです。「なぜこのファイルの先頭に'use client'があるのか」が分かると、Next.jsのエラーの多くが意味を持ちます。まず全体の形を見てください。
まずはこの例を見てみましょう
// ===== page.tsx(何も書かない = サーバーで動く)=====
export default async function Page() {
const posts = await fetchPosts(); // データを取って…
return (
<main>
{posts.map((p) => <article key={p.id}>{p.title}</article>)}
<LikeButton /> {/* クリックが必要な部分だけ、別部品に */}
</main>
);
}
// ===== like-button.tsx(ブラウザで動く部品)=====
"use client"; // ← この1行が「ブラウザ行き」の宣言
export function LikeButton() {
const [likes, setLikes] = useState(0); // useState はブラウザ専用
return <button onClick={() => setLikes(likes + 1)}>♥ {likes}</button>;
}ページ本体はサーバー(軽くて速い)、ボタンだけブラウザ(操作できる)。この分担が理想形です。
何も書かなければサーバーで動く
コンポーネントはサーバーで実行され、完成したHTMLになって届きます。ブラウザに送るコードが減り、軽くて速いです。
'use client'=ブラウザ行きの宣言
例のLikeButtonのように、ファイル先頭に書くとブラウザで動きます。useState・onClickなどの「操作する機能」はこちら専用です。
使い分けの原則
データを取って表示するだけ → サーバー。クリック・入力・stateが要る → ブラウザ。「操作が必要な部分だけ」を小さく切り出すのが理想です。
レビュー観点:'use client'の乱発
AIがページ全体に'use client'を付けていたら、サーバーの利点を捨てているサイン。「操作部分だけ分離できない?」が定番の指摘です。
コード例
// ===== app/posts/page.tsx(サーバー: 既定)=====
// データを取得して表示するだけ → サーバーで完結
export default async function Page() {
const posts = await fetchPosts();
return (
<main>
<h1>投稿一覧</h1>
{posts.map((p) => <article key={p.id}>{p.title}</article>)}
<LikeButton /> {/* 対話が必要な部分だけ「ブラウザ」の部品に */}
</main>
);
}
// ===== like-button.tsx(ブラウザ)=====
"use client";
import { useState } from "react";
export function LikeButton() {
const [likes, setLikes] = useState(0);
return <button onClick={() => setLikes(likes + 1)}>♥ {likes}</button>;
}「サーバーの器に、ブラウザの島を埋め込む」構造。AIのコードを読むときは、まず各ファイルの先頭1行('use client'の有無)を見ましょう。
ステップ 1 / 2
※ カリキュラムの内容はAIが生成しており、誤りが含まれる場合があります。正確な情報は公式ドキュメント等でご確認ください。