3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsのServer Actionsをもっと便利に安全に使うnext-safe-actionを紹介したい

Posted at

前置き

突然ですが、Next.jsのServer Actionsって便利ですよね?皆さん使っていますか?
ただ、もっとこんなことができたらいいのになぁって思う瞬間があるかもしれません。例えば、

  • エラーハンドリングを共通化したい
  • 認可処理を共通化したい
  • 上記をやりつつ型安全を維持したい

と思ったことはありませんか?

そんな時は、next-safe-actionを使用すれば全て解決するかもしれません。

next-safe-actionとは

next-safe-actionは、Next.jsのServer Actionsをラップし、安全に扱えるようにするライブラリです。

公式ドキュメント:next-safe-action

主な特徴は以下の通りです。

  • 型安全なServer Actionsの作成
  • 一元的なエラーハンドリング
  • Middlewareによる共通処理の適用

使い方

インストール

まずは、next-safe-actionをインストールします。
ついでに、client側のformライブラリ(react-hook-form)とvalidation libraryをインストールします。

npm install next-safe-action zod react-hook-form @hookform/resolvers

createSafeActionの使い方

createSafeActionを使用すると、型安全なServer Actionを簡単に作成できます。

'use server';

import { createSafeAction } from 'next-safe-action';
import { z } from 'zod';

const action = createSafeActionClient({
  // エラーハンドリング処理
  handleServerError(e, utils) {
    // You can access these properties inside the `utils` object.
    const { clientInput, bindArgsClientInputs, metadata, ctx } = utils;

    // Log to console.
    console.error("Action error:", e.message);

    // 共通的なエラー処理
    return "エラーが発生しました";
  },
});

export const sampleSchema = z.object({
  name: z.string(),
});

export const sampleAction = action
  .schema(sampleSchema)
  .action(async ({ input }) => {
    return `Hello ${input.name}`
  });

export default action;

このようにcreateSafeActionを使うことで、共通的なactionを定義することができます。
ここでは、「共通的なエラーハンドリング」が実現できます。
さらに、各actionではshcemaを指定することで、簡単に型を指定することができます。

Middlewareの活用

Middlewareを利用することで、認可処理やロギングを共通化できます。

import { createSafeAction } from 'next-safe-action';
import { z } from 'zod';

const action = createSafeActionClient({
  // エラーハンドリング処理
  handleServerError(e, utils) {
    // You can access these properties inside the `utils` object.
    const { clientInput, bindArgsClientInputs, metadata, ctx } = utils;

    // Log to console.
    console.error("Action error:", e.message);

    // 共通的なエラー処理
    return "エラーが発生しました";
  },
}).use(async ({ next }) => {
    const session = cookies().get("session")?.value;

    if (!session) {
      throw new Error("Session not found!");
    }

    const userId = await getUserIdFromSessionId(session);

    if (!userId) {
      throw new Error("Session is not valid!");
    }

    // Return the next middleware with `userId` value in the context
    return next({ ctx: { userId } });
  });;

actionの定義の後に.useと繋げることで共通的なロギング処理や認可処理も定義することが可能です!

Client側の実装

Client側では、react-hook-formzodを組み合わせてフォームを作成し、next-safe-actionを活用できます。

'use client';

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useAction } from "next-safe-action/hooks";
import { z } from 'zod';
import { sampleAction, sampleSchema } from '../actions';
import { useState } from 'react';


type FormData = z.infer<typeof sampleSchema>;

export default function Form() {
  // useActionで簡単にaction処理を呼び出せます!
  const { execute } = useAction(sampleAction);

  const { control, handleSubmit } = useForm<FormData>({
    defaultValues: {
      name: "John",
    },
    resolver: zodResolver(sampleSchema),
  });

  return (
    <form onSubmit={handleSubmit(execute)}>
      <div>
        <label>名前:</label>
        <input {...register('name')} />
      </div>
      <button type="submit">送信</button>
      {response && <p>サーバーからの応答: {response}</p>}
    </form>
  );
}

このフォームでは、

  • react-hook-form でフォーム管理
  • zod で入力バリデーション
  • next-safe-action で型安全なServer Actionの呼び出し

を実現しています。

clinet側ではuseActionが超絶便利!
https://next-safe-action.dev/docs/execute-actions/hooks/useaction
処理だけではなく、statusなども取得できるし、callback系の処理を引数に指定できるので成功時の処理などを簡単にわかりやすく指定できます!

まとめ

Next.jsのServer Actionsをより安全に使うためには、next-safe-actionが非常に便利です。

  • createSafeActionで型安全・エラーハンドリングを強化
  • middlewareで認可処理を共通化
  • react-hook-formzodでClient側のフォームを型安全に実装

この記事では伝えていない機能もたくさんあるので是非みなさん使ってみてください!

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?