コンテンツへスキップ
App Routerはじめにデータ更新

データの更新方法

Next.jsでは、ReactのServer Functionsを使用してデータを更新できます。このページでは、Server Functionsの作成呼び出し方法を説明します。

サーバー関数の作成

Server Functionはuse server` ディレクティブを使用して定義できます。このディレクティブは、非同期関数の先頭に置いてその関数をServer Functionとしてマークするか、別のファイルの先頭に置いてそのファイルのすべてのエクスポートをマークするために使用できます。

app/lib/actions.ts
export async function createPost(formData: FormData) {
  'use server'
  const title = formData.get('title')
  const content = formData.get('content')
 
  // Update data
  // Revalidate cache
}
 
export async function deletePost(formData: FormData) {
  'use server'
  const id = formData.get('id')
 
  // Update data
  // Revalidate cache
}

サーバーコンポーネント

Server Componentsでは、関数本体の先頭に"use server"ディレクティブを追加することで、Server Functionをインラインで定義できます

app/page.tsx
export default function Page() {
  // Server Action
  async function createPost(formData: FormData) {
    'use server'
    // ...
  }
 
  return <></>
}

クライアントコンポーネント

Client ComponentsでServer Functionを定義することはできません。ただし、ファイルの先頭に"use server"ディレクティブが記述されているファイルからServer Functionをインポートすることで、Client ComponentsからServer Functionを呼び出すことができます

app/actions.ts
'use server'
 
export async function createPost() {}
app/ui/button.tsx
'use client'
 
import { createPost } from '@/app/actions'
 
export function Button() {
  return <button formAction={createPost}>Create</button>
}

サーバー関数の呼び出し

Server Functionを呼び出す主な方法は2つあります

  1. ServerおよびClient Componentsにおけるフォーム
  2. Client Componentsにおけるイベントハンドラ

フォーム

ReactはHTMLの<form>要素を拡張し、HTMLのactionプロパティでServer Functionを呼び出せるようにします。

フォームで呼び出されると、関数は自動的にFormDataオブジェクトを受け取ります。データはネイティブのFormDataメソッドを使用して抽出できます。

app/ui/form.tsx
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>
  )
}
app/actions.ts
'use server'
 
export async function createPost(formData: FormData) {
  const title = formData.get('title')
  const content = formData.get('content')
 
  // Update data
  // Revalidate cache
}

知っておくと便利: actionプロパティに渡される場合、Server FunctionsはServer Actionsとしても知られています。

イベントハンドラ

Client Componentでは、onClickなどのイベントハンドラを使用してServer Functionを呼び出すことができます。

app/like-button.tsx
'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>
    </>
  )
}

保留状態の表示

Server Functionの実行中には、ReactのuseActionStateフックを使用してローディングインジケータを表示できます。このフックはpendingブール値を返します

app/ui/button.tsx
'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>
  )
}

キャッシュの再検証

更新を実行した後、Server Function内でrevalidatePathまたはrevalidateTagを呼び出すことで、Next.jsのキャッシュを再検証し、更新されたデータを表示できます

app/lib/actions.ts
import { revalidatePath } from 'next/cache'
 
export async function createPost(formData: FormData) {
  'use server'
  // Update data
  // ...
 
  revalidatePath('/posts')
}

リダイレクト

更新を実行した後、ユーザーを別のページにリダイレクトしたい場合があります。これは、Server Function内でredirectを呼び出すことで実現できます

app/lib/actions.ts
'use server'
 
import { redirect } from 'next/navigation'
 
export async function createPost(formData: FormData) {
  // Update data
  // ...
 
  redirect('/posts')
}

APIリファレンス

このページで言及されている機能の詳細については、APIリファレンスを参照してください。