🐷

Next.js Server Actions実行後に何かしたいときの3パターン

2025/01/31に公開
3

Next.jsのServer Actions表記はいつServer Functionsに変わるんだろう?と気になっている@zaruです、こんにちは。今回はNext.jsでServer Actions実行後になにかしたいときの実装を3パターン紹介します。

パターン1: Server Actionsで後処理

最初はもうシンプルにServer Actionsの関数内で実行します。今回はリダイレクトを実行する例にします。バックエンド側で実行できるような後処理であれば原則Server Actions内で制御するのが良いと思います。

page.tsx
import { submit } from "./action";

export default function Page() {
  return (
    <form action={submit}>
      <button type="submit">Submit</button>
    </form>
  );
}
action.ts
"use server";

import { redirect } from "next/navigation";

export async function submit(formData: FormData) {
  // いろいろ処理した後にリダイレクトさせる
  redirect("/");
}

パターン2: ClientComponentで後処理

ここからはClientComponent側の後処理になります。Server Actions関数をラップする関数を用意し、その中で後処理を実装します。あとは通常のServer Actionsと同様に action 属性に渡せばOKです。

page.tsx
"use client";

import { submit } from "@/app/after_submit/handle_action/action";
import { useRouter } from "next/navigation";

export default function Page() {
  const router = useRouter();
  // Server Actionsの関数をラップする関数を作って呼び出す
  const handleSubmit = async (formData: FormData) => {
    await submit(formData);
    // 処理完了後にリダイレクトさせる
    router.push("/");
  };
  return (
    <form action={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}
action.ts
"use server";

export async function submit(formData: FormData) {
  // Server Actionsの必要な処理
}

パターン3: useActionStateで後処理

最後に useActionState もしくは useFormState を使った例です。パターン2と同様にServer Actions関数をラップします。違いはそのラップした関数を useActionState もしくは useFormState にわたすようにする点と引数を変更することです。

page.tsx
"use client";

import { submit } from "@/app/after_submit/use_action_state/action";
import { useRouter } from "next/navigation";
import { useActionState } from "react";

export default function Page() {
  const router = useRouter();
  // Server Actionsの関数をラップし、useActionStateに合った関数を作って呼び出す
  const handleSubmit = async (_prevState: object, formData: FormData) => {
    await submit();
    // 処理完了後にリダイレクトさせる
    router.push("/");
    return {};
  };
  const [_state, action] = useActionState(handleSubmit, {});
  return (
    <form action={action}>
      <input type={"text"} name={"name"} />
      <button type="submit">Submit</button>
    </form>
  );
}
action.ts
"use server";

export async function submit(formData: FormData) {
  // Server Actionsの必要な処理
}

おまけ: after

Next.js v15からは after という機能が登場しています。これを使うと、LayoutやPage、Server Actionsなどのレンダリング後あるいは実行後に after で定義した処理を実行することができます。今回の例で出したリダイレクトは用途に合いませんが、ロギングやレポート送信などで活用することができます。

Server Actionsで after を使った例です。

"use server";

import { redirect } from "next/navigation";
import { after } from "next/server";

export async function submit(formData: FormData) {
  after(() => {
    console.log("Server Actionsが実行されたよ!!!");
  });
  redirect("/");
}

after の処理はレンダリングをブロックしないので、使い所としては利用者に影響を与えず何らかの処理をしたい時ですね。

3
ムーザルちゃんねる

Discussion