今回は、Next.jsのServer Component(app directory構成)でnext-safe-action
を使う実験をしてみました。
最近のNext.jsではServer Actionsが注目されていますが、Server Componentから直接next-safe-action
を呼び出して、型安全な共通処理として使えるかどうか検証してみました。
サンプルプロジェクト
- GitHubリポジトリ: https://github.com/gosutesu/sample-next-safe-action
特にsrc/app/test/[name]/page-server-component.ts
で試しています。
next-safe-actionとは?
next-safe-action
は、Server Actionsを型安全かつ共通化して扱えるライブラリです。
zodと組み合わせてスキーマバリデーションを行い、Server ComponentやClient Componentから同一のインターフェースで呼び出すことができます。
公式リポジトリ: https://github.com/TheEdoRan/next-safe-action
Server Componentでの使い方
今回のサンプルでは、パラメータを受け取ってサーバーサイドで処理を行い、その結果をServer Componentで利用するというシンプルな構成です。
例えば、下記のようにsrc/app/test/[name]/page-server-component.ts
でActionを定義しました。
"use server";
import { actionClient } from "@/client/safe-client";
import { z } from "zod";
const Input = z.object({
name: z.string().min(1, "Name is required"),
});
export type InputType = z.infer<typeof Input>;
export const testServerAction = actionClient
.schema(Input)
.action(async ({ parsedInput }) => {
return { message: `Hello, ${parsedInput.name}` };
});
Server Componentからの呼び出し例(src/app/test/[name]/page-server-component.ts
):
import { testServerAction } from "./page-server-component";
type PageProps = {
params: {
name: string;
};
};
export const Page = async ({params} : PageProps) => {
const sentence = await testServerAction({name: params.name});
return (
<div className="flex flex-col items-center justify-center h-screen">
<h1 className="text-2xl font-bold mb-4">Test Page</h1>
<p className="text-lg">This is a test page.</p>
<p className="text-lg mt-4">{sentence?.data?.message}</p>
</div>
);
}
export default Page;
このように、Server Componentから直接Actionを呼び出し、バリデーションや型安全性を確保しつつ、共通化されたサーバーサイド処理を呼べることが分かりました。
まとめ
所管
- Server Componentから
next-safe-action
を直接呼び出し、共通処理を安全に実行できることを確認しました。 - 画面描画時と画面操作時のサーバー側の処理の共通化の何かヒントになるかも?
- DB接続エラー処理とかまとめて書けそう
- アプリ側のアクセスログとかまとめてかけていいかんじ
課題
- 予期せぬサーバーサイドのエラーが起きた時って、画面描画時と画面操作時で同じでもいい?(アプリの要件次第かも)
- 処理が呼び出させる順番ってどうなっているんだろう
- 15系でのキャッシュとの関連ってどうなっているんだろう
- 予想通りの動きはしているが本当にできている??
ここら辺の課題を解決していって今後のプロジェクトの改善をしていきたいなぁと思っている次第です
もし興味があればぜひサンプルプロジェクトを試してみてください!