🐷

server actionsについて記録

2024/09/03に公開

最近、多くのフレームワークでserver actionsのサポートが次々と始まっています。例えば、Next.js、Remix、Astroなどです。

私の印象では、server actionsは最初にRemixが提案し、その後多くのフレームワークが追随し始めました。この機能が登場する前は、多くのフレームワークがクライアント/サーバー間の双方向通信を通じてフォーム送信を実装していました。以下に簡単な例を示して説明します:


import { useForm, SubmitHandler } from "react-hook-form"

type Inputs = {
  example: string
  exampleRequired: string
}

export default function App() {
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<Inputs>()
  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data)

  console.log(watch("example"))

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />

      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}

      <input type="submit" />
    </form>
  )
}

この例では、react-hook-formを使用してフォームの送信を実装しています。ユーザーがフォームを送信すると、onSubmit関数が呼び出されます。この関数はクライアント側で実行され、fetchリクエストを通じてサーバーに送信されます。サーバーはリクエストを受け取ると、onSubmit関数を実行し、結果をクライアントに返します。実際、このような方法はjQueryの時代からすでに一般的でした。では、なぜ今server actionsが人気になっているのでしょうか?

以前のフローは次のようなものでした:

  1. ユーザーがクライアント側でフォームを送信
  2. クライアントがfetchリクエストを通じてサーバーに送信
  3. サーバーがリクエストを受け取り、onSubmit関数を実行し、結果をクライアントに返す
  4. クライアントが結果を受け取り、ページを更新

新しい、server actionsに基づくフローはどのようなものでしょうか?まずコードを見てみましょう:

export default function Page() {
  async function createInvoice(formData: FormData) {
    'use server'
 
    const rawFormData = {
      customerId: formData.get('customerId'),
      amount: formData.get('amount'),
      status: formData.get('status'),
    }
 
    // mutate data
    // revalidate cache
  }
 
  return <form action={createInvoice}>...</form>
}

これにより、以下のような利点がもたらされます:

  1. これは完全にWeb標準に準拠しており、ユーザーがJavaScriptを無効にしても正常に動作することが期待できます。
  2. このパターンに基づいて、server actionsは簡単にキャッシュをクリアでき、送信後のページ更新が容易になります。
  3. フロントエンドとバックエンドで一貫したバリデーションロジックを実装するのが非常に簡単です。例えば、バックエンドとクライアント側で同じバリデーション関数を使用できます。
  4. 実は最も言いたかったことですが、この実装方法は開発者の直感に非常に合っています。例えば、クライアント側では、フォームの送信だけを気にすればよく、フォームの送信結果を気にする必要はありません。フォームの送信結果は自然とフレームワークが処理します。

次に、明らかにいくつかの欠点、あるいはコストについて述べる必要があります:

  1. use serveractionmutateuseActionStateなどの新しい概念を学ぶ必要があります。
  2. フォームアクションのデフォルトのデータ形式はFormDataで、フロントエンドでよく使用されるJSON形式と一致しないため、変換のプロセスが必要です。
  3. フロントエンドは独自のサーバーを持つ必要があり、CSRモードでは明らかに使用できません。
  4. フロントエンドはserver actionsのAPIを使用する必要があります。これは、以前よく使用されていたreact-hook-formなどのライブラリが再適応する必要があることを意味します。少なくとも現時点では、react-hook-formはserver actionsを完全にサポートしていません。

この記事では、server actionsの実装方法と私の考えを簡単に記録したいと思います。今後しばらくの間、Remix、Next.js、Astroでのserver actionsの使用方法と、それぞれの特徴について詳しく記録していく予定です。

Discussion