← inaro.devAI駆動開発 学習ツール
中級

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が生成しており、誤りが含まれる場合があります。正確な情報は公式ドキュメント等でご確認ください。