本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

Client Component とは何か

Client Component は、ファイルの先頭に use client と書くことでブラウザにも送られる React コンポーネントです。

いつ必要になるのか

判断は単純です。ブラウザにしかないものが必要かどうかだけを見ます。

必要なものClient にする
useState useReducer などの状態要る
useEffect要る
onClick onChange などのイベント要る
window document localStorage要る
ブラウザ専用のライブラリ要る
表示するだけ要らない
データを取ってきて並べるだけ要らない

迷ったら「押せるか」「変わるか」で考えてください。押せる/変わるならブラウザが必要です。

書き方

ファイルのいちばん上、import より前に一度だけ書きます。

'use client'
 
import { useState } from 'react'
 
export function Counter() {
  const [n, setN] = useState(0)
  return <button onClick={() => setN(n + 1)}>{n}</button>
}

サーバーでも動くことに注意

Client Component が画面に出るまで。サーバーでも一度描かれる
  1. Server
    サーバーで一度描く

    初回表示の HTML を作るため。window も localStorage もここには無い。

  2. Browser
    HTML が表示される

    見た目はもう出ている。ただしこの時点では押しても何も起きない。

  3. Browser
    JavaScript を読み込んで hydration

    同じ内容をもう一度描き、イベントを繋ぐ。ここで初めて押せるようになる。

名前から「ブラウザだけで動く」と思いがちですが、違います。Client Component も、最初の表示のためにサーバー側で一度実行されます。

Client Component が押せるようになるまで
  1. Server
    サーバーで実行して HTML を作る

    初回表示を速くするため。ここではまだ押せない。

  2. Browser
    ブラウザへ JavaScript が届く

    この部品のコードが、そのままブラウザへ配られる。

  3. Browser
    ブラウザで実行して繋ぐ(hydration)

    同じ内容を描き直し、イベントを接続する。ここで押せるようになる。

だから Client Component の中に window.innerWidth をそのまま書くと、手順1で落ちます。ブラウザ限定の処理は useEffect の中に置いてください。

「Client Component = ブラウザだけ」ではなく「Client Component = ブラウザにも送られる」と覚えるほうが正確です。

サーバーで描いた内容と、ブラウザで描き直した内容が食い違うと、hydration のエラーになります(Hydration とは何か・Hydration failed の直し方)。

境界は下にだけ伝わる

'use client' を書いたファイルから import したものは、すべて Client Component になります。逆はありません。親には影響しません。

印を1つ書くと、そこから下がまとめてブラウザ側になる
サーバー側に残る
Page.tsx
ブラウザにも送られる
Panel.tsx(use client)
Badge.tsx(印は無いが巻き込まれる)

越えられる: Page から Panel へ渡した値

越えられない: Panel から上へは広がらない。Page は Server のまま

だから、付ける位置が上へ行くほど、ブラウザへ送る JavaScript が増えます。

大きくなってきたら children で逃がす

Client Component の中に重い表示を抱えたくなったら、import するのではなく children として外から渡します。渡されたものは境界に巻き込まれません。

// app/page.tsx(Server のまま)
export default async function Page() {
  const items = await db.item.findMany()
  return (
    <Panel>
      <ItemList items={items} />   {/* Server のまま */}
    </Panel>
  )
}

Panel の中で import { ItemList } と書くと、その瞬間に ItemList も Client になります。children で渡すか import するかで結果が変わるのがここです。

受け取れる props には制限がある

Server から Client へ渡せるのは、値だけです。

  • 渡せる: 文字列・数値・配列・プレーンなオブジェクト・Date・Map・Set
  • 渡せない: 関数・クラスのインスタンス

関数を渡すとエラーになるので、ハンドラは Client Component の内側で定義します。

よくある誤解

'use client' を付けたら、そのファイルはブラウザでしか動かない?

動きます。上に書いたとおり、初回はサーバーでも実行されます。

async にできない?

Next.js 16.3.5 ではビルドは通ります。「Client Component は async にできない」と書いてある記事は多いのですが、実際に試すと通ります。ただし読み込み中の表示が扱いにくくなるので、use フックか useEffect を使うほうが素直です。

迷ったら付けておけばいい?

逆です。付けるほどブラウザへ送る JavaScript が増えます。必要なところにだけ付けてください。

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

このファイルには use client がありません。どうなりますか。

この問題を解くこのテーマの問題 3 問