😀
【Next.js 14】Server Actionsで実現するモダンなフォーム処理
はじめに
ウェブアプリケーション開発において、フォーム処理は最も一般的でありながら複雑なタスクの1つです。Next.js 14で正式に導入されたServer Actionsは、このフォーム処理を劇的に簡素化する新機能です。本記事では、Server Actionsを活用したモダンなフォーム処理の実装方法について解説します。
Server Actionsとは
Server ActionsはNext.js 14で正式リリースされた機能で、クライアントサイドから直接サーバーサイドの関数を呼び出すことができます。これにより、APIルートを自前で作成する必要がなくなり、フォーム送信やデータ処理をより直感的に記述できるようになります。
主な特徴:
- クライアントコンポーネントからサーバーサイドコードを直接実行可能
- TypeScriptの型安全性を保ったまま開発可能
- プログレッシブエンハンスメントをサポート
- デフォルトでCSRF対策が組み込まれている
基本的な実装例
// app/actions.ts
"use server";
export async function createPost(formData: FormData) {
const title = formData.get("title");
const content = formData.get("content");
// データベースへの保存処理など
await db.post.create({
data: { title, content }
});
revalidatePath("/posts");
}
// app/page.tsx
import { createPost } from "@/app/actions";
export default function PostForm() {
return (
<form action={createPost}>
<input type="text" name="title" required />
<textarea name="content" required />
<button type="submit">作成</button>
</form>
);
}
メリットとユースケース
1. シンプルなデータ送信
従来のAPIルート作成やfetch処理が不要に。フォーム送信が劇的に簡潔になります。
2. リアルタイムバリデーション
useFormStateと組み合わせることで、サーバーサイドバリデーションを簡単に実装可能:
"use client";
import { useFormState } from "react-dom";
import { createPost } from "./actions";
const initialState = { errors: {} };
export function PostForm() {
const [state, formAction] = useFormState(createPost, initialState);
return (
<form action={formAction}>
<input name="title" />
{state.errors?.title && <p>{state.errors.title}</p>}
{/* ... */}
</form>
);
}
3. 楽観的UI更新
useOptimisticフックと組み合わせて、投稿前にUIを即時更新:
"use client";
import { useOptimistic } from "react";
import { sendMessage } from "./actions";
export function Chat({ messages }) {
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(state, newMessage) => [...state, { text: newMessage, sending: true }]
);
async function formAction(formData: FormData) {
const message = formData.get("message");
addOptimisticMessage(message);
await sendMessage(message);
}
return (
<>
{optimisticMessages.map((msg, i) => (
<div key={i}>{msg.text} {msg.sending && "送信中..."}</div>
))}
<form action={formAction}>
<input type="text" name="message" />
<button type="submit">送信</button>
</form>
</>
);
}
ベストプラクティス
-
大規模アプリケーションでの整理
- 関連するServer Actionsを
actionsディレクトリにグループ化 - 1ファイルにつき1つのリソース(posts/actions.tsなど)
- 関連するServer Actionsを
-
セキュリティ対策
- 常に
"use server"ディレクティブを使用 - 権限チェックを必ず実装
- 入力値の検証をサーバーサイドで実施
- 常に
-
パフォーマンス最適化
- 頻繁に変更されるデータには
dynamic = 'force-dynamic' - 大きなファイルアップロードには
useUploadThingなどのライブラリを検討
- 頻繁に変更されるデータには
既存手法との比較
| 方法 | コード量 | パフォーマンス | 開発体験 |
|---|---|---|---|
| APIルート + fetch | 多い | 普通 | 複雑 |
| tRPC | 普通 | 良い | 良い |
| Server Actions | 少ない | 優れている | 非常に良い |
制限事項と注意点
- 現時点では、Server Actionsのサイズ制限(1MB)がある
- 複雑な非同期処理には向かない場合がある
- エラーハンドリングには注意が必要
- 現状、Edge Runtimeでは完全な機能が利用できない
まとめ
Next.js 14のServer Actionsは、フォーム処理とデータ変更のパラダイムを変える強力な機能です。APIルートの作成やクライアントサイドの複雑な状態管理が不要になり、開発者はビジネスロジックに集中できるようになります。
まだ発展途上の機能ではありますが、今後さらに進化していくことが予想されます。フォームを多用するアプリケーション開発においては、ぜひこの新しいアプローチを試してみてください。
Discussion