この記事の対象読者
- App Routerで
use clientをどこに付けるか迷う人 - Server ComponentとClient Componentの分け方を知りたい人
- Pages Router経験からApp Routerへ移る人
本題に入る前に
この話は、Next.js App Routerで画面やコンポーネントを作る人を想定しています。どこまでをサーバー側に置き、どこからブラウザ側で動かすかを考えたい人に向けた内容です。
最近、App Routerを触るときに迷いやすいのが「どこからブラウザで動かすべきか」だと感じます。ボタンのクリックや入力欄の状態はブラウザ側で必要ですが、画面全体をすべてブラウザ側に寄せる必要はありません。
たとえば、一覧はサーバーで取得して表示するだけなのに、フィルターの開閉ボタンだけブラウザで動かしたいことがあります。このときページ全体をClient Componentにすると、必要以上に範囲が広くなります。ちょっともったいないです。
最初は "use client" を付ければ動くので安心したくなります。でも、どこに境界を置くかを少し考えると、コードの読みやすさや役割分担が変わります。この記事では、その判断の入口を扱います。
Next.js App Routerでは、デフォルトでServer Componentとして扱われます。
一方で、useState やクリックイベントなど、ブラウザ上で動く処理が必要な場所はClient Componentにします。
Client Componentにする目安
次のようなものはClient Componentが必要です。
-
useStateを使う -
useEffectを使う -
onClickなどのイベントを使う - ブラウザAPIを使う
全部をClientにしない理由
App Routerを触り始めたとき、迷ったらページ全体に "use client" を付けたくなることがあります。
小さいサンプルではそれでも動きます。ただ、ページ全体をClient Componentにすると、Server Componentとして扱える部分までブラウザ側のコードに寄ってしまいます。
たとえば、画面の大部分はサーバー側でデータを取得して表示するだけで、ボタン1つだけが開閉状態を持つ場合があります。この場合は、ページ全体ではなくボタン周辺だけをClient Componentにするほうが自然です。
ページ全体: Server Component
開閉ボタン: Client Component
境界を小さくすると、どこがブラウザで動く必要があるのかも読みやすくなります。
"use client";
import { useState } from "react";
export function ToggleButton() {
const [open, setOpen] = useState(false);
return <button onClick={() => setOpen(!open)}>{open ? "閉じる" : "開く"}</button>;
}
小さく分ける
ページ全体をClient Componentにするより、操作が必要な部品だけをClient Componentにすると整理しやすいです。
まとめ
use client は困ったら全部に付けるものではなく、ブラウザで動く必要がある境界に付けるものです。
まずは「状態やイベントが必要な部品はどこか」を探すのがおすすめです。