こんにちは。あのちっくです。
commmune Advent Calendar 2023 13日目の記事はNext.jsのServerActionsの話です。
どうぞよろしくお願いします。
Serve rActions
Next.js 14からServer ActionsがStableになりました。
私はtRPCが大好きでよく使っているのですが、ServerActionsもtRPCのようにzodを使ってinput,outputのスキーマ定義を行ってバリデーションも効くようにしたかったので、自作の仕組みappAction
を作りました。
export const sampleAction = appAction({
input: z.object({ nickname: z.string(), title: z.string() }),
output: z.object({
postId: z.string(),
title: z.string(),
name: z.string(),
}),
}).resolve(async (input) => {
return {
postId: "xxx",
title: input.title,
name: `${input.nickname} さん`,
};
});
使い方は簡単で、上記のコードのようにaction定義を行うと、resolve内の関数実行時にバリデーターが実行されるというものです。型チェックも効きます。
next-safe-action
自作してから[next-safe-action]というライブラリがあることに気づいたので紹介させてください。
基本的な使い方としては、インターフェースはすこし違いますが、機能はだいたい同じです。outputの型定義も行うかどうかの違いぐらい。
"use server";
import { z } from "zod";
import { action } from "@/lib/safe-action";
const schema = z.object({ nickname: z.string(), title: z.string() });
export const sampleAction = action(schema, async ({ nickname, title }) => {
return {
postId: "xxx",
title: input.title,
name: `${input.nickname} さん`,
};
});
いい感じですね。
さらに、next-safe-actionには追加で様々な機能があります。
非同期処理用のhooks
next-safe-actionにはuseAction
というhooks関数が用意されています。
export default function Test() {
const { execute, result } = useAction(sampleAction);
return (
<div>
<button
onClick={() => {
execute({postId:'xx', title:'yy', name:'zz'});
}}>
Send
</button>
{result.data?.name ? <p>{result.data.name}</p> : ''}
</div>
);
}
というようにawait
せずにactionを実行して使うことが出来るようになります。
callback
action statusの変化に応じたコールバンク関数を定義して使うことが出来ます。
middleware
メインとなるaction関数を実行する前に、ユーザー認証処理をして、引数にユーザーデータを与えるような事をしたいことがあるとおもいます。
そういったときのためにmiddlewareの仕組みも存在します。
良さそう
next-safe-action、とてもおすすめです。
ぜひ使ってみてください。