在 Next.js 中,你可以使用 React 的服務(wù)器函數(shù)(Server Functions)來更新數(shù)據(jù)。 本頁將介紹如何創(chuàng)建和調(diào)用服務(wù)器函數(shù)。
通過使用 use server
指令可以定義服務(wù)器函數(shù)。你可以將該指令放在一個(gè)異步函數(shù)的頂部來標(biāo)記該函數(shù)為服務(wù)器函數(shù),或者放在一個(gè)單獨(dú)文件的頂部來標(biāo)記該文件的所有導(dǎo)出內(nèi)容。我們建議在大多數(shù)情況下使用單獨(dú)的文件。
'use server'
export async function createPost(formData: FormData) {}
export async function deletePost(formData: FormData) {}
通過在函數(shù)體頂部添加 "use server"
指令,可以在服務(wù)器組件中內(nèi)聯(lián)服務(wù)器函數(shù):
export default function Page() {
// 服務(wù)器操作
async function createPost() {
'use server'
// 更新數(shù)據(jù)
// ...
}
return <></>
}
在客戶端組件中無法定義服務(wù)器函數(shù)。但是,可以通過從一個(gè)頂部有 "use server"
指令的文件中導(dǎo)入它們來調(diào)用服務(wù)器函數(shù):
'use server'
export async function createPost() {}
'use client'
import { createPost } from '@/app/actions'
export function Button() {
return <button formAction={createPost}>創(chuàng)建</button>
}
調(diào)用服務(wù)器函數(shù)主要有兩種方式:
React 擴(kuò)展了 HTML 的 <form>
元素,允許通過 HTML action
屬性調(diào)用服務(wù)器函數(shù)。
在表單中調(diào)用時(shí),函數(shù)會(huì)自動(dòng)接收 FormData
對象。你可以使用原生的 FormData
方法提取數(shù)據(jù):
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">創(chuàng)建</button>
</form>
)
}
'use server'
export async function createPost(formData: FormData) {
const title = formData.get('title')
const content = formData.get('content')
// 更新數(shù)據(jù)
// 重新驗(yàn)證緩存
}
小貼士:當(dāng)傳遞給
action
屬性時(shí),服務(wù)器函數(shù)也被稱為服務(wù)器操作。
你可以在客戶端組件中通過使用事件處理程序(如 onClick
)來調(diào)用服務(wù)器函數(shù)。
'use client'
import { incrementLike } from './actions'
import { useState } from 'react'
export default function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes)
return (
<>
<p>總點(diǎn)贊數(shù): {likes}</p>
<button
onClick={async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
}}
>
點(diǎn)贊
</button>
</>
)
}
在執(zhí)行服務(wù)器函數(shù)時(shí),可以使用 React 的 useActionState
鉤子顯示加載指示器。此鉤子返回一個(gè) 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 /> : '創(chuàng)建帖子'}
</button>
)
}
在執(zhí)行更新后,可以通過在服務(wù)器函數(shù)中調(diào)用 revalidatePath
或 revalidateTag
來重新驗(yàn)證 Next.js 緩存并顯示更新后的數(shù)據(jù):
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
// 更新數(shù)據(jù)
// ...
revalidatePath('/posts')
}
在執(zhí)行更新后,你可能需要將用戶重定向到不同的頁面。可以在服務(wù)器函數(shù)中調(diào)用 redirect
來實(shí)現(xiàn):
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// 更新數(shù)據(jù)
// ...
redirect('/posts')
}
閱讀 API 參考 ,了解有關(guān)本頁中提到的功能的更多信息。
更多建議: