如何更新数据
你可以使用 React 的 服务器函数 更新 Next.js 中的数据。本页将介绍如何使用 create 和 invoke 服务器功能。
¥You can update data in Next.js using React's Server Functions. This page will go through how you can create and invoke Server Functions.
创建服务器函数
¥Creating Server Functions
可以使用 use server
指令定义服务器函数。你可以将指令放在异步函数的顶部以将该函数标记为服务器函数,或者放在单独文件的顶部以标记该文件的所有导出。我们建议在大多数情况下使用单独的文件。
¥A Server Function can be defined by using the use server
directive. You can place the directive at the top of an asynchronous function to mark the function as a Server Function, or at the top of a separate file to mark all exports of that file. We recommend using a separate file in most instances.
'use server'
export async function createPost(formData: FormData) {}
export async function deletePost(formData: FormData) {}
'use server'
export async function createPost(formData) {}
export async function deletePost(formData) {}
服务器组件
¥Server Components
可以通过将 "use server"
指令添加到函数主体顶部,在服务器组件中内联服务器函数:
¥Server Functions can be inlined in Server Components by adding the "use server"
directive to the top of the function body:
export default function Page() {
// Server Action
async function createPost() {
'use server'
// Update data
// ...
return <></>
}
export default function Page() {
// Server Action
async function createPost() {
'use server'
// Update data
// ...
}
return <></>
}
客户端组件
¥Client Components
无法在客户端组件中定义服务器函数。但是,你可以通过从顶部包含 "use server"
指令的文件中导入它们来在客户端组件中调用它们:
¥It's not possible to define Server Functions in Client Components. However, you can invoke them in Client Components by importing them from a file that has the "use server"
directive at the top of it:
'use server'
export async function createPost() {}
'use server'
export async function createPost() {}
'use client'
import { createPost } from '@/app/actions'
export function Button() {
return <button formAction={createPost}>Create</button>
}
'use client'
import { createPost } from '@/app/actions'
export function Button() {
return <button formAction={createPost}>Create</button>
}
调用服务器函数
¥Invoking Server Functions
有两种主要方式可以调用服务器函数:
¥There are two main ways you can invoke a Server Function:
-
服务器和客户端组件中的 表单
¥Forms in Server and Client Components
-
客户端组件中的 事件处理程序
¥Event Handlers in Client Components
表单
¥Forms
React 扩展了 HTML <form>
元素,允许使用 HTML action
属性调用服务器函数。
¥React extends the HTML <form>
element to allow Server Function to be invoked with the HTML action
prop.
在表单中调用时,该函数会自动接收 FormData
对象。你可以使用原生 FormData
方法 提取数据:
¥When invoked in a form, the function automatically receives the FormData
object. You can extract the data using the native FormData
methods:
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>
)
}
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
}
'use server'
export async function createPost(formData) {
const title = formData.get('title')
const content = formData.get('content')
// Update data
// Revalidate cache
}
很高兴知道:当传递给
action
prop 时,服务器函数也称为服务器操作。¥Good to know: When passed to the
action
prop, Server Functions are also known as Server Actions.
事件处理程序
¥Event Handlers
你可以使用事件处理程序(例如 onClick
)在客户端组件中调用服务器函数。
¥You can invoke a Server Function in a Client Component by using event handlers such as 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>
</>
)
}
'use client'
import { incrementLike } from './actions'
import { useState } from 'react'
export default function LikeButton({ initialLikes }) {
const [likes, setLikes] = useState(initialLikes)
return (
<>
<p>Total Likes: {likes}</p>
<button
onClick={async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
}}
>
Like
</button>
</>
)
}
显示待处理状态
¥Showing a pending state
在执行服务器函数时,你可以使用 React 的 useActionState
钩子显示加载指示器。此钩子返回 pending
布尔值:
¥While executing a Server Function, you can show a loading indicator with React's useActionState
hook. This hook returns a pending
boolean:
'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>
)
}
'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>
)
}
重新验证缓存
¥Revalidating the cache
执行更新后,你可以通过在服务器函数中调用 revalidatePath
或 revalidateTag
来重新验证 Next.js 缓存并显示更新的数据:
¥After performing an update, you can revalidate the Next.js cache and show the updated data by calling revalidatePath
or revalidateTag
within the Server Function:
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
// Update data
// ...
revalidatePath('/posts')
}
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData) {
// Update data
// ...
revalidatePath('/posts')
}
重定向
¥Redirecting
你可能希望在执行更新后将用户重定向到其他页面。你可以通过在服务器函数中调用 redirect
来执行此操作:
¥You may want to redirect the user to a different page after performing an update. You can do this by calling redirect
within the Server Function:
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// Update data
// ...
redirect('/posts')
}
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData) {
// Update data
// ...
redirect('/posts')
}