跳到內容

如何更新資料

您可以使用 React 的 伺服器函式在 Next.js 中更新資料。本頁面將介紹如何建立調用伺服器函式。

建立伺服器函式

伺服器函式可以使用 use server 指令來定義。您可以將指令放在非同步函式的頂部,以將該函式標記為伺服器函式,或放在單獨檔案的頂部,以標記該檔案的所有匯出。我們建議在大多數情況下使用單獨的檔案。

app/lib/actions.ts
'use server'
 
export async function createPost(formData: FormData) {}
 
export async function deletePost(formData: FormData) {}

伺服器元件

伺服器函式可以通過將 "use server" 指令添加到函式主體頂部,內嵌在伺服器元件中

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

用戶端元件

無法在用戶端元件中定義伺服器函式。但是,您可以透過從頂部具有 "use server" 指令的檔案匯入它們,在用戶端元件中調用它們

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>
}

調用伺服器函式

有兩種主要方式可以調用伺服器函式

  1. 表單在伺服器和用戶端元件中
  2. 事件處理器在用戶端元件中

表單

React 擴展了 HTML <form> 元素,允許使用 HTML action 屬性調用伺服器函式。

當在表單中調用時,該函式會自動接收 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 屬性時,伺服器函式也稱為伺服器行為

事件處理器

您可以在用戶端元件中使用事件處理器(例如 onClick)來調用伺服器函式。

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>
    </>
  )
}

顯示擱置狀態

在執行伺服器函式時,您可以使用 React 的 useActionState Hook 來顯示載入指示器。此 Hook 會傳回一個 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>
  )
}

重新驗證快取

執行更新後,您可以調用伺服器函式內的 revalidatePathrevalidateTag 來重新驗證 Next.js 快取並顯示更新後的資料

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

重新導向

您可能希望在執行更新後將使用者重新導向到不同的頁面。您可以通過調用伺服器函式內的 redirect 來做到這一點

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