サーバーアクション (Server Actions)

Next.js は React アクションと統合され、サーバーサイドのデータ変更 (server mutations) のための組み込みソリューションを提供します。

規約

Next.js プロジェクトでサーバーアクションを有効にするには、実験的serverActions フラグを有効にします。

next.config.js
module.exports = {
  experimental: {
    serverActions: true,
  },
}

サーバーアクションは2つの場所で定義できます:

  • 使用するコンポーネント内(サーバーコンポーネントのみ)
  • 再利用のために別ファイル内(クライアントおよびサーバーコンポーネント)。1つのファイルに複数のサーバーアクションを定義できます。

サーバーコンポーネントでの使用

関数本体の先頭に "use server" ディレクティブを付けた非同期関数を定義してサーバーアクションを作成します。"use server" はこの関数がサーバー上でのみ実行されることを保証します。

この関数はシリアライズ可能な引数シリアライズ可能な戻り値を持つ必要があります。

app/page.js
export default function ServerComponent() {
  async function myAction() {
    'use server'
    // ...
  }
}

クライアントコンポーネントでの使用

インポート方法

別ファイルに "use server" ディレクティブをファイルの先頭に記述してサーバーアクションを作成します。その後、クライアントコンポーネントにサーバーアクションをインポートします:

app/actions.js
'use server'

export async function myAction() {
  // ...
}
app/client-component.jsx
'use client'

import { myAction } from './actions'

export default function ClientComponent() {
  return (
    <form action={myAction}>
      <button type="submit">カートに追加</button>
    </form>
  )
}

補足: トップレベルの "use server" ディレクティブを使用する場合、その下のすべてのエクスポートはサーバーアクションと見なされます。1つのファイルに複数のサーバーアクションを含めることができます。

プロパティとして渡す

場合によっては、サーバーアクションをプロパティとしてクライアントコンポーネントに渡したいことがあります。

<ClientComponent updateItem={updateItem} />
app/client-component.jsx
'use client'

export default function ClientComponent({ myAction }) {
  return (
    <form action={myAction}>
      <input type="text" name="name" />
      <button type="submit">アイテムを更新</button>
    </form>
  )
}

引数のバインド

bind メソッドを使用してサーバーアクションに引数をバインドできます。これにより、一部の引数が既にバインドされた新しいサーバーアクションを作成できます。これはサーバーアクションに追加の引数を渡したい場合に便利です。

app/client-component.jsx
'use client'

import { updateUser } from './actions'

export function UserProfile({ userId }) {
  const updateUserWithId = updateUser.bind(null, userId)

  return (
    <form action={updateUserWithId}>
      <input type="text" name="name" />
      <button type="submit">ユーザー名を更新</button>
    </form>
  )
}

そして、updateUser サーバーアクションはフォームデータに加えて常に userId 引数を受け取ります:

app/actions.js
'use server'

export async function updateUser(userId, formData) {
  // ...
}

補足: サーバーアクションの .bind はサーバーコンポーネントとクライアントコンポーネントの両方で動作します。プログレッシブエンハンスメントもサポートしています。

呼び出し方法

サーバーアクションは以下の方法で呼び出せます:

  • action の使用: React の action プロパティを使用すると、<form> 要素でサーバーアクションを呼び出せます。
  • formAction の使用: React の formAction プロパティを使用すると、<form> 内の <button><input type="submit"><input type="image"> 要素を処理できます。
  • startTransition によるカスタム呼び出し: actionformAction を使わずに startTransition を使用してサーバーアクションを呼び出します。この方法ではプログレッシブエンハンスメント無効になります

プログレッシブエンハンスメント

プログレッシブエンハンスメントにより、JavaScript が無効な場合でも <form> が適切に機能します。これにより、フォームの JavaScript がまだ読み込まれていない場合や読み込みに失敗した場合でも、ユーザーはフォームと対話してデータを送信できます。

React アクション(サーバーとクライアントの両方)は、次の2つの戦略のいずれかを使用してプログレッシブエンハンスメントをサポートします:

  • サーバーアクションが直接 <form> に渡された場合、JavaScript が無効でもフォームはインタラクティブです。
  • クライアントアクション<form> に渡された場合、フォームは依然としてインタラクティブですが、アクションはフォームがハイドレートされるまでキューに入れられます。React はアクションを優先するため、迅速に処理されます。

どちらの場合も、フォームはハイドレーションが行われる前にインタラクティブになります。サーバーアクションにはクライアント JavaScript に依存しないという追加の利点がありますが、クライアントアクションで必要な追加の動作を構成してもインタラクティブ性を犠牲にすることはありません。

サイズ制限

デフォルトでは、サーバーアクションに送信されるリクエストボディの最大サイズは1MBで、大量のデータを解析する際のサーバーリソースの過剰な消費を防ぎます。

ただし、serverActionsBodySizeLimit オプションを使用してこの制限を設定できます。バイト数または bytes がサポートする任意の文字列形式(例: 1000'500kb''3mb')を指定できます。

next.config.js
module.exports = {
  experimental: {
    serverActions: true,
    serverActionsBodySizeLimit: '2mb',
  },
}

追加リソース

以下の React API ページは現在ドキュメント作成中です:

  • "use server"
  • action (🚧)
  • formAction (🚧)
  • useFormStatus (🚧)
  • useFormState (🚧)
  • useOptimistic (🚧)