データの更新方法
Next.jsでは、Reactのサーバー関数を使用してデータを更新できます。このページでは、サーバー関数の作成方法と呼び出し方法について説明します。
サーバー関数の作成
サーバー関数はuse server
ディレクティブを使用して定義できます。このディレクティブを非同期関数の先頭に配置してその関数をサーバー関数としてマークするか、別のファイルの先頭に配置してそのファイルのすべてのエクスポートをマークできます。ほとんどの場合、別のファイルを使用することをお勧めします。
'use server'
export async function createPost(formData: FormData) {}
export async function deletePost(formData: FormData) {}
サーバーコンポーネント
サーバー関数は、関数本体の先頭に"use server"
ディレクティブを追加することで、サーバーコンポーネント内にインライン化できます:
export default function Page() {
// Server Action
async function createPost() {
'use server'
// Update data
// ...
return <></>
}
クライアントコンポーネント
クライアントコンポーネント内でサーバー関数を定義することはできません。ただし、先頭に"use server"
ディレクティブが記述されたファイルからインポートすることで、クライアントコンポーネント内でサーバー関数を呼び出すことができます:
'use server'
export async function createPost() {}
'use client'
import { createPost } from '@/app/actions'
export function Button() {
return <button formAction={createPost}>Create</button>
}
サーバー関数の呼び出し
サーバー関数を呼び出す主な方法は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">Create</button>
</form>
)
}
'use server'
export async function createPost(formData: FormData) {
const title = formData.get('title')
const content = formData.get('content')
// Update data
// Revalidate cache
}
補足:
action
プロパティに渡されると、サーバー関数は_サーバーアクション_とも呼ばれます。
イベントハンドラ
クライアントコンポーネントでは、onClick
などのイベントハンドラを使用してサーバー関数を呼び出すことができます。
'use client'
import { incrementLike } from './actions'
import { useState } from 'react'
export default function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes)
return (
<>
<p>Total Likes: {likes}</p>
<button
onClick={async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
}}
>
Like
</button>
</>
)
}
処理中の状態を表示する
サーバー関数を実行している間、ReactのuseActionState
フックを使って読み込みインジケーターを表示できます。このフックはpending
ブール値を返します:
'use client'
import { useActionState } from 'react'
import { createPost } from '@/app/actions'
import { LoadingSpinner } from '@/app/ui/loading-spinner'
export function Button() {
const [state, action, pending] = useActionState(createPost, false)
return (
<button onClick={async () => action()}>
{pending ? <LoadingSpinner /> : 'Create Post'}
</button>
)
}
キャッシュの再検証
更新を実行した後、サーバー関数内でrevalidatePath
またはrevalidateTag
を呼び出すことで、Next.jsのキャッシュを再検証し、更新されたデータを表示できます:
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
// Update data
// ...
revalidatePath('/posts')
}
リダイレクト
更新を実行した後、ユーザーを別のページにリダイレクトしたい場合があります。サーバー関数内でredirect
を呼び出すことでこれを実現できます:
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// Update data
// ...
redirect('/posts')
}