境界の設計

上に書くほど、巻き込む

"use client" は、書いたファイルよりをまとめてブラウザ側にします。だから、どこに書くかで巻き込む量がまるで変わります。

app/items/page.tsx "use client" ← ここに書くと └ ItemList.tsx ブラウザ側 └ ItemCard.tsx ブラウザ側 └ LikeButton ブラウザ側

ページの先頭に書いた瞬間、そのページの中身は全部ブラウザ側になります。実際にクリックを受け取るのは末端の LikeButton 1つだけなのに、一覧も、カードも、まとめてブラウザに送られます。

広い境界の代償

巻き込まれた部品の代償は3つあります。

  • JavaScript の量が増える — 押されもしない部品のコードまで配られる
  • サーバーの利点を失う — データベースを直接読む書き方が使えなくなる
  • 最初の表示が遅くなる — 届いた JavaScript が動くまで待つ部分が増える

どれも画面を見ただけでは気付きません。動いてしまうので、そのまま何ヶ月も広い境界のまま進むことがあります。

末端に押し込む

直し方は決まっています。"use client" を、実際にクリックや state が要るいちばん小さい部品まで下げることです。

app/items/page.tsx サーバー └ ItemList.tsx サーバー └ ItemCard.tsx サーバー └ LikeButton "use client" ← ここまで下げる

こうすると、ブラウザに配られるのはボタン1つぶんだけになります。一覧の組み立てはサーバーで終わり、届く HTML には商品名がすでに入っています。

設計の指針は1つです。上から下ろすのではなく、下から必要な場所にだけ置く。 迷ったら、いま "use client" を書こうとしているファイルより小さい部品に切り出せないかを先に考えます。

演習

広がってしまった境界を、末端まで押し戻します。

ヒント

ItemList.tsx
LikeButton.tsx
data.ts
page.tsx
layout.tsx
プレビュー

できているか

  • 商品が4件並んでいる
  • サーバー側のページで件数を出している
  • 商品名が出ている
  • いいねボタンが各行にある
  • いいねを押すと数が増える
  • クリックを受け取る末端の部品だけを宣言している
  • ページ全体をブラウザ側に巻き込んでいない
  • 一覧部品もサーバーに戻している
  • データの置き場所をブラウザ側に引き込んでいない