更新数据
你可以使用 React 的服务端函数在 Next.js 中更新数据。本页将介绍如何创建和调用服务端函数。
什么是服务端函数?
服务端函数是在服务器上运行的异步函数。它们可以通过网络请求从客户端调用,这就是为什么它们必须是异步的。
在 action 或修改上下文中,它们也被称为服务端操作。
按照约定,服务端操作是与 startTransition 一起使用的异步函数。当函数被以下方式使用时,这会自动发生:
- 使用 
actionprop 传递给<form>。 - 使用 
formActionprop 传递给<button>。 
在 Next.js 中,服务端操作与框架的缓存架构集成。当操作被调用时,Next.js 可以在单个服务器往返中返回更新的 UI 和新数据。
在幕后,操作使用 POST 方法,只有这个 HTTP 方法可以调用它们。
创建服务端函数
可以通过使用 use server 指令来定义服务端函数。你可以将指令放在异步函数的顶部来标记该函数为服务端函数,或者放在单独文件的顶部来标记该文件的所有导出。
- TypeScript
 - JavaScript
 
app/lib/actions.ts
export async function createPost(formData: FormData) {
  'use server'
  const title = formData.get('title')
  const content = formData.get('content')
  // 更新数据
  // 重新验证缓存
}
export async function deletePost(formData: FormData) {
  'use server'
  const id = formData.get('id')
  // 更新数据
  // 重新验证缓存
}
app/lib/actions.js
export async function createPost(formData) {
  'use server'
  const title = formData.get('title')
  const content = formData.get('content')
  // 更新数据
  // 重新验证缓存
}
export async function deletePost(formData) {
  'use server'
  const id = formData.get('id')
  // 更新数据
  // 重新验证缓存
}
服务端组件
可以通过在函数体顶部添加 "use server" 指令在服务端组件中内联服务端函数:
- TypeScript
 - JavaScript
 
app/page.tsx
export default function Page() {
  // 服务端操作
  async function createPost(formData: FormData) {
    'use server'
    // ...
  }
  return <></>
}
app/page.js
export default function Page() {
  // 服务端操作
  async function createPost(formData: FormData) {
    'use server'
    // ...
  }
  return <></>
}
注意: 服务端组件默认支持渐进增强,这意味着调用服务端操作的表单即使在 JavaScript 尚未加载或已禁用的情况下也会被提交。
客户端组件
无法能在客户端组件中定义服务端函数。但是,你可以通过从顶部有 "use server" 指令的文件导入它们来在客户端组件中调用它们:
- TypeScript
 - JavaScript
 
app/actions.ts
'use server'
export async function createPost() {}
app/actions.js
'use server'
export async function createPost() {}
- TypeScript
 - JavaScript
 
app/ui/button.tsx
'use client'
import { createPost } from '@/app/actions'
export function Button() {
  return <button formAction={createPost}>添加</button>
}
app/ui/button.js
'use client'
import { createPost } from '@/app/actions'
export function Button() {
  return <button formAction={createPost}>添加</button>
}
注意: 在客户端组件中,调用服务端操作的表单如果 JavaScript 尚未加载,将排队提交,并将优先进行水合。水合后,浏览器在表单提交时不会刷新。
将操作作为 props 传递
你也可以将操作作为 prop 传递给客户端组件:
<ClientComponent updateItemAction={updateItem} />
- TypeScript
 - JavaScript
 
app/client-component.tsx
'use client'
export default function ClientComponent({
  updateItemAction,
}: {
  updateItemAction: (formData: FormData) => void
}) {
  return <form action={updateItemAction}>{/* ... */}</form>
}
app/client-component.js
'use client'
export default function ClientComponent({ updateItemAction }) {
  return <form action={updateItemAction}>{/* ... */}</form>
}
调用服务端函数
有两种主要方式可以调用服务端函数: