コース一覧
Next.jsフルスタック:サーバー・データ取得・API
境界の設計

Next.jsフルスタック:サーバー・データ取得・API

Server ComponentsとClient Components、use client、サーバーfetch、asyncコンポーネント、動的ルート、params、notFound、キャッシュ、Route Handler、GET・POST API、Server Actions、フォームを扱う全24レッスンのフルスタックコースです。fleamaの商品取得と出品機能をNext.js内へ実装します。

1
Server / Client Components
01. サーバーで動く部品10分
02. Server Components15分
03. use clientの宣言15分
04. どちらに置くか15分
05. 境界をまたぐ合成15分
06. 境界の設計15分
07. つくる - 部品の仕分け20分
08. 第4章クイズ15分
2
データ取得と動的ルート
01. サーバーでfetch15分
02. asyncコンポーネント15分
03. 動的ルート15分
04. paramsを受け取る15分
05. notFoundで404にする15分
06. キャッシュのきほん10分
07. 検索をサーバーで15分
08. つくる - サーバー取得化20分
09. 第5章クイズ15分
3
API Routesとフォーム
01. Route Handler15分
02. GET APIを作る15分
03. POST APIを作る15分
04. Server Actionsの触り15分
05. フォーム実装15分
06. つくる - 受け口の完成20分
07. 第6章クイズ15分

境界の設計

境界をどこまで下げるか

上に書くほど、巻き込む

"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" を書こうとしているファイルより小さい部品に切り出せないかを先に考えます。

演習

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

ヒント

件数は items.length で取れます。{items.length} 件 のように書きます

use client を消しても、表示するだけの部品はそのまま動きます

境界は上から下ろすのではなく、必要な末端にだけ置きます

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

できているか

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