サーバーアクションとミューテーション
Server Actionsは、サーバーで実行される**非同期関数**です。これらは、Next.js アプリケーションでフォームの送信やデータのミューテーションを処理するために、サーバーコンポーネントとクライアントコンポーネントの両方で呼び出すことができます。
🎥 動画: Server Actions を使用したミューテーションの詳細はこちら → YouTube (10分)。
規約
Server Action は、React の "use server"
ディレクティブを使用して定義できます。このディレクティブを `async` 関数の先頭に配置して関数を Server Action としてマークすることも、個別のファイルの先頭に配置してそのファイルのエクスポートすべてを Server Action としてマークすることもできます。
サーバーコンポーネント
サーバーコンポーネントは、インライン関数レベルまたはモジュールレベルの `"use server"` ディレクティブを使用できます。Server Action をインラインで記述するには、関数本体の先頭に `"use server"` を追加します。
export default function Page() {
// Server Action
async function create() {
'use server'
// Mutate data
}
return '...'
}
クライアントコンポーネント
クライアントコンポーネントで Server Action を呼び出すには、新しいファイルを作成し、そのファイルの先頭に `"use server"` ディレクティブを追加します。ファイル内のエクスポートされたすべての関数は、クライアントコンポーネントとサーバーコンポーネントの両方で再利用できる Server Action としてマークされます。
'use server'
export async function create() {}
'use client'
import { create } from './actions'
export function Button() {
return <button onClick={() => create()}>Create</button>
}
propsとしてアクションを渡す
Server Action を Client Component に props として渡すこともできます。
<ClientComponent updateItemAction={updateItem} />
'use client'
export default function ClientComponent({
updateItemAction,
}: {
updateItemAction: (formData: FormData) => void
}) {
return <form action={updateItemAction}>{/* ... */}</form>
}
通常、Next.js TypeScript プラグインは `client-component.tsx` 内の `updateItemAction` にフラグを付けます。これは、関数が通常クライアントとサーバーの境界を越えてシリアル化できないためです。しかし、`action` という名前または `Action` で終わる props は Server Actions を受け取ると仮定されます。これは TypeScript プラグインが実際に Server Action を受け取っているのか、それとも通常の関数を受け取っているのかを認識しないため、単なるヒューリスティックに過ぎません。ランタイムの型チェックは、誤って関数をクライアントコンポーネントに渡してしまわないように引き続き保証します。
動作
- サーバーアクションは、
<form>
要素の `action` 属性を使用して呼び出すことができます。- サーバーコンポーネントはデフォルトでプログレッシブエンハンスメントをサポートしており、JavaScript がまだロードされていない場合や無効になっている場合でもフォームが送信されます。
- クライアントコンポーネントでは、Server Actions を呼び出すフォームは、JavaScript がまだロードされていない場合、クライアントのハイドレーションを優先して送信をキューに入れます。
- ハイドレーション後、フォーム送信時にブラウザはリフレッシュされません。
- Server Actions は `
- Server Actions は Next.js のキャッシングおよび再検証アーキテクチャと統合されています。アクションが呼び出されると、Next.js は更新された UI と新しいデータの両方を単一のサーバーラウンドトリップで返すことができます。
- 内部では、アクションは `POST` メソッドを使用し、この HTTP メソッドのみがそれらを呼び出すことができます。
- Server Actions の引数と戻り値は React によってシリアル化可能である必要があります。シリアル化可能な引数と値のリストについては、React のドキュメント (serializable arguments and values) を参照してください。
- Server Actions は関数です。これは、アプリケーションのどこでも再利用できることを意味します。
- Server Actions は、使用されるページまたはレイアウトからランタイムを継承します。
- Server Actions は、使用されるページまたはレイアウトから `maxDuration` のようなフィールドを含むルートセグメント設定を継承します。
例
フォーム
React は HTML の <form>
要素を拡張し、`action` プロパティを使用して Server Actions を呼び出せるようにします。
フォーム内で呼び出されると、アクションは自動的に `FormData` オブジェクトを受け取ります。React の `useState` を使用してフィールドを管理する必要はなく、代わりにネイティブの `FormData` メソッドを使用してデータを抽出できます。
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>
}
知っておくと良いこと
- 例: ローディングとエラー状態を持つフォーム
- 多くのフィールドを持つフォームを扱う場合、JavaScript の
Object.fromEntries()
とentries()
メソッドを組み合わせて使用することを検討してください。例: `const rawFormData = Object.fromEntries(formData)`。注意点としては、`formData` には追加の `$ACTION_` プロパティが含まれることです。- 詳細については、React の
<form>
ドキュメントを参照してください。
追加の引数を渡す
JavaScript の `bind` メソッドを使用して、Server Action に追加の引数を渡すことができます。
'use client'
import { updateUser } from './actions'
export function UserProfile({ userId }: { userId: string }) {
const updateUserWithId = updateUser.bind(null, userId)
return (
<form action={updateUserWithId}>
<input type="text" name="name" />
<button type="submit">Update User Name</button>
</form>
)
}
Server Action は、フォームデータに加えて `userId` 引数を受け取ります。
'use server'
export async function updateUser(userId: string, formData: FormData) {}
知っておくと良いこと:
- 別の方法として、フォームの非表示入力フィールドとして引数を渡すこともできます (例: ``)。ただし、この値はレンダリングされた HTML の一部となり、エンコードされません。
- `.bind` はサーバーコンポーネントとクライアントコンポーネントの両方で機能します。また、プログレッシブエンハンスメントもサポートしています。
ネストされたフォーム要素
Server Action は、`
この情報は役に立ちましたか?