データ更新方法
Next.jsではReactのサーバー関数 (Server Functions)を使用してデータを更新できます。このページではサーバー関数の作成と呼び出し方法について説明します。
サーバー関数 (Server Functions)
サーバー関数はサーバー上で実行される非同期関数です。クライアントからネットワークリクエスト経由で呼び出されるため、サーバー関数は本質的に非同期です。action
の一部として呼び出される場合、サーバーアクション (Server Actions) とも呼ばれます。
慣例として、action
はstartTransition
に渡される非同期関数です。サーバー関数は以下の場合に自動的にstartTransition
でラップされます:
<form>
のaction
プロパティに渡された場合<button>
のformAction
プロパティに渡された場合useActionState
に渡された場合
サーバー関数の作成
サーバー関数はuse server
ディレクティブを使用して定義できます。ディレクティブを非同期関数の先頭に配置して関数をサーバー関数としてマークするか、ファイルの先頭に配置してそのファイルのすべてのエクスポートをマークできます。
export async function createPost(formData: FormData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')
// データ更新
// キャッシュ再検証
}
export async function deletePost(formData: FormData) {
'use server'
const id = formData.get('id')
// データ更新
// キャッシュ再検証
}
export async function createPost(formData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')
// データ更新
// キャッシュ再検証
}
export async function deletePost(formData) {
'use server'
const id = formData.get('id')
// データ更新
// キャッシュ再検証
}
サーバーコンポーネント (Server Components)
サーバーコンポーネント内では、関数本体の先頭に"use server"
ディレクティブを追加することでサーバー関数をインラインで定義できます:
export default function Page() {
// サーバーアクション
async function createPost(formData: FormData) {
'use server'
// ...
}
return <></>
}
export default function Page() {
// サーバーアクション
async function createPost(formData) {
'use server'
// ...
}
return <></>
}
クライアントコンポーネント (Client Components)
クライアントコンポーネントでサーバー関数を定義することはできません。ただし、"use server"
ディレクティブが先頭にあるファイルからインポートすることで、クライアントコンポーネントで呼び出すことができます:
'use server'
export async function createPost() {}
'use server'
export async function createPost() {}
サーバー関数の呼び出し
サーバー関数を呼び出す主な方法は2つあります:
フォーム
ReactはHTMLの<form>
要素を拡張し、HTMLのaction
プロパティでサーバー関数を呼び出せるようにしています。
フォームで呼び出された場合、関数は自動的にFormData
オブジェクトを受け取ります。ネイティブのFormData
メソッドを使用してデータを抽出できます:
import { createPost } from '@/app/actions'
export function Form() {
return (
<form action={createPost}>
<input type="text" name="title" />
<input type="text" name="content" />
<button type="submit">作成</button>
</form>
)
}
import { createPost } from '@/app/actions'
export function Form() {
return (
<form action={createPost}>
<input type="text" name="title" />
<input type="text" name="content" />
<button type="submit">作成</button>
</form>
)
}
'use server'
export async function createPost(formData: FormData) {
const title = formData.get('title')
const content = formData.get('content')
// データ更新
// キャッシュ再検証
}
'use server'
export async function createPost(formData) {
const title = formData.get('title')
const content = formData.get('content')
// データ更新
// キャッシュ再検証
}
補足:
action
プロパティに渡された場合、サーバー関数は_サーバーアクション (Server Actions)_ とも呼ばれます。
イベントハンドラ
クライアントコンポーネントではonClick
などのイベントハンドラを使用してサーバー関数を呼び出せます。
使用例
処理中状態の表示
サーバー関数の実行中は、ReactのuseActionState
フックを使用してローディングインジケータを表示できます。このフックはpending
ブール値を返します:
キャッシュの再検証
更新を実行した後、サーバー関数内でrevalidatePath
またはrevalidateTag
を呼び出すことでNext.jsのキャッシュを再検証し、更新されたデータを表示できます:
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
'use server'
// データ更新
// ...
revalidatePath('/posts')
}
import { revalidatePath } from 'next/cache'
export async function createPost(formData) {
'use server'
// データ更新
// ...
revalidatePath('/posts')
}
リダイレクト
更新後にユーザーを別のページにリダイレクトしたい場合があります。サーバー関数内でredirect
を呼び出すことで実現できます:
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// データ更新
// ...
redirect('/posts')
}
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData) {
// データ更新
// ...
redirect('/posts')
}