Server Actions (データ更新)
前章では、サーバー側の処理(バックエンド)を行う手段としてAPI Route を学びました。クライアント側(ブラウザ)からこのバックエンドAPIを fetch などのメソッドを用いてリクエストするのが一般的な方法でした。
しかし、Next.js の Server Actions を使うと、 API を作らずに、コンポーネントから直接サーバー側の関数を呼び出す ことができます。
Server Actions とは?
関数の中に "use server" と書くだけで、その関数がサーバー上で実行されるようになります。
これにより、クライアント(ブラウザ)の JavaScript が減り、コードも直感的になります。
仕組みと推奨される理由
「関数をインポートして実行しているだけ」に見えますが、実際の 裏側では POST リクエストが送信されています 。
Next.js は、ビルド時に Server Action の関数ごとに独自の URL エンドポイントを生成し、クライアントから呼び出された際に、Next.js 独自のプロトコルを使って通信を行っています。(ネットワークタブを見ると、特殊なヘッダーやペイロードが確認できます)
なぜこれが推奨されるのか? (BFFアーキテクチャ)
Server Actions は、 BFF (Backend For Frontend) の思想を体現した機能だからです。
- フロントエンドのためのバックエンド : 画面に必要な処理だけを、画面のコードのすぐ近く(または同じファイル)に書くことができます。
- セキュア : コンポーネントから直接呼んでいますが、処理自体はサーバー内でのみ実行されるため、データベースの認証情報などがブラウザに漏れることはありません。
- API定義の手間削減 : REST API の設計やドキュメント作成の手間を省き、UI の開発スピードを最大化できます。
基本的な使い方(フォーム送信)
簡単な「Todo追加」の例で見てみましょう。
1. Server Action の定義
通常は actions.ts などの別ファイルに定義するのが管理しやすいです。
src/app/actions.ts"use server"; // ファイルの先頭に書くと、中身はすべてServer Actionになる import { revalidatePath } from "next/cache"; // サーバー上で実行される関数 export async function addTodo(formData: FormData) { // フォームから値を取得 const title = formData.get("title")?.toString(); if (!title) return; // ここで本来はデータベースに保存する console.log("Saving todo:", title); // キャッシュを更新して画面をリフレッシュ(重要!) revalidatePath("/"); }
2. コンポーネントから呼び出し
form タグの action 属性に、インポートした関数を渡すだけです。
src/app/page.tsximport { addTodo } from "./actions"; export default function Page() { return ( <main className="p-4"> <h1>Todo App</h1> {/* action属性に関数を直接渡す */} <form action={addTodo} className="flex gap-2"> <input name="title" type="text" className="border p-2" placeholder="新しいタスク" /> <button type="submit" className="bg-blue-500 text-white p-2"> 追加 </button> </form> </main> ); }
これだけで、ボタンを押すと裏側でサーバーへのRPC(リモートプロシージャコール)が発生し、addTodo 関数が実行されます。fetch も useState も使っていません。非常にシンプルですね!
クライアントコンポーネントからの呼び出し
ボタンにクリックイベント (onClick) をつけて Server Action を呼び出したい場合は、コンポーネント側を "use client" にする必要がありますが、呼び出し方は同じです。
"use client"; import { addTodo } from "./actions"; export default function ClientButton() { return ( <button onClick={async () => await addTodo(/* ... */)}> 追加 </button> ); }
※ フォームの場合は action 属性を使う方がプログレッシブエンハンスメント(JS無効でも動く)の観点で推奨されます。
まとめ
Server Actions は、Next.js App Router 時代のデータ更新の標準のやり方です。
- APIルート不要 :
route.tsを書く必要がない。 - 型安全 : 引数や戻り値に型が付くので開発しやすい。
- 直感的 : 関数を呼ぶ感覚でサーバーと通信できる。
データの取得(Fetch)だけでなく、データの更新(Action)も習得すれば、本格的なWebアプリが作れるようになります。