YASD-TECH
YASD TECH
# Next.js
# TypeScript

従来のformとServer Action利用時のform

投稿日:2025/1/3

更新日:2025/1/3

ttitleImage

前置き

Next.jsでサーバーアクションに入門している時にformの投げ方色々あるな、、と感じたので整理してみました。今回はformの値の投げ方のみにフォーカスした記事になります。

formから値を投げるには基本的にはactionformActiononSubmit の属性を利用することになります。actionformAction はサーバーサイドで、onSubmmitはクライアントサイド(ブラウザ上)で機能します。

action

HTML の<form>タグに使用される属性で、フォームを送信した際の送信先 URL を指定する。

主にサーバーにフォームデータを送信するためのエンドポイントを書く。

index
<form action="/submit" method="POST">
    <input type="text" name="name" />
    <button type="submit">送信</button>
</form>
  • 補足:
    • 通常、method 属性 (GETPOST) と組み合わせて使用される。
    • クライアントサイドでは action による動作がなく、サーバーサイドで処理される。
    • actionになにも指定していない場合、formのあるページのパスに自動的に飛ぶ

formAction

HTMLの<button> または <input> タグで使用され、フォーム送信時の送信先 URL をオーバーライドする。

特定のボタンや入力項目で別々の送信先を指定したい場合に利用

index
<form action="/default">
    <input type="text" name="name" />
    <button type="submit" formAction="/submit1">送信1</button>
    <button type="submit" formAction="/submit2">送信2</button>
</form>

  • 補足:
    • action 属性よりも優先順位が高い(この場合、/defaultには飛ばない)
    • フォームの一部だけ異なる処理をする場合に便利
    • action同様、クライアントサイドでは formAction による動作がなく、サーバーサイドで処理される。

onSubmit

HTML の<form>タグに使用される属性で、フォーム全体が送信される際に JavaScript で処理するためのイベントハンドラ。ブラウザで動いてくれるのでフォーム送信時にバリデーションやカスタム処理実行することができる

index
<form onSubmit="return validateForm()">
    <input type="text" name="name" />
    <button type="submit">送信</button>
</form>

React の場合

index
const handleSubmit = (e) => {
    // デフォルトの送信を防ぐ
    e.preventDefault();
    console.log('フォーム送信');
};

return (
    <form onSubmit={handleSubmit}>
        <input type="text" name="name" />
        <button type="submit">送信</button>
    </form>
);

  • 補足:
    • フォーム全体の送信イベントに特化
    • 第一引数指定でいろんなアクションが可能

Server Action

さて、本題です。

これのなにが嬉しいかというと従来サーバーでしかできなかった処理をAPIを利用しなくても良くなりました。どういうことかというとactionformAction 属性に従来ではAPIのエンドポイントを指定していましたが、これを非同期関数を指定することによってAPIエンドポイントを作成せずとも利用できるようになりました。

page.tsx
// action属性利用の場合
"use client";
import { submitForm } from "./action";

export default function Page() {
  return (
    <form action={submitForm}>
      <input type="text" name="name" />
      <button type="submit">送信</button>
    </form>
  );
}

// formAction属性利用の場合
"use client";
import { submmitForm } from "./action";

export default function Page() {
  return (
    <form>
      <input type="text" name="name" />
      <button formAction={submitForm} type="submit">送信</button>
    </form>
  );
}
action.ts
"use server";
export async function submitForm(formData: FormData) {
  const name = formData.get("name");
  console.log(name);
}

ポイントは大きく2つです。

  1. use serverを記載してサーバーアクションであることを明示すること。
  2. async を記載して非同期関数にすることです。

デフォルトで引数を1つとることが可能で、この中に送信されたデータがオブジェクトとして入ってきます(formDataの中身です)。こうすることで、APIを用意せずともサーバーサイドでの処理を記載することができます。

まとめ

今回はフォームの投げ方のみにフォーカスした記事を書いてみました。

JSが無効化されている環境でも利用できる点、API作成の必要がない点では便利だなーと思うとともにNext.jsでの責任範囲が膨大になりそうでその辺のアーキテクチャは考えないとなと思いました。

Index

  • 前置き
  • action
  • formAction
  • onSubmit
  • React の場合
  • Server Action
  • まとめ