Skip to main content

服务器操作


Next.js 与 React Actions 集成,为 服务器突变 提供内置解决方案。

Next.js integrates with React Actions to provide a built-in solution for server mutations.

惯例

服务器操作可以在两个地方定义:

Server Actions can be defined in two places:

  • 在使用它的组件内部(仅限服务器组件)。
  • 在单独的文件(客户端和服务器组件)中,以实现可重用性。 你可以在单个文件中定义多个服务器操作。

带有服务器组件

通过在函数体顶部使用 "使用服务器" 指令定义异步函数来创建服务器操作。 "use server" 确保此函数仅在服务器上执行。

Create a Server Action by defining an asynchronous function with the "use server" directive at the top of the function body. "use server" ensures this function is only ever executed on the server.

该函数应该有 可序列化的参数可序列化的返回值

This function should have serializable arguments and a serializable return value.

export default function ServerComponent() {
async function myAction() {
'use server'
// ...
}
}

使用客户端组件

导入

在单独的文件中创建服务器操作,并在文件顶部添加 "use server" 指令。 然后,将服务器操作导入到你的客户端组件中:

Create your Server Action in a separate file with the "use server" directive at the top of the file. Then, import the Server Action into your Client Component:

'use server'

export async function myAction() {
// ...
}
'use client'

import { myAction } from './actions'

export default function ClientComponent() {
return (
<form action={myAction}>
<button type="submit">Add to Cart</button>
</form>
)
}

很高兴知道: 使用顶层 "use server" 指令时,下面的所有导出都将被视为服务器操作。 你可以在单个文件中包含多个服务器操作。

属性

在某些情况下,你可能希望将服务器操作作为属性传递给客户端组件。

In some cases, you might want to pass down a Server Action to a Client Component as a prop.

<ClientComponent myAction={updateItem} />
'use client'

export default function ClientComponent({ updateItem }) {
return (
<form action={updateItem}>
<input type="text" name="name" />
<button type="submit">Update Item</button>
</form>
)
}

具有约束力的参数

你可以使用 bind 方法将参数绑定到服务器操作。 这允许你创建一个已绑定一些参数的新服务器操作。 当你想要将额外的参数传递给服务器操作时,这非常有用。

You can bind arguments to a Server Action using the bind method. This allows you to create a new Server Action with some arguments already bound. This is beneficial when you want to pass extra arguments to a Server Action.

'use client'

import { updateUser } from './actions'

export function UserProfile({ userId }) {
const updateUserWithId = updateUser.bind(null, userId)

return (
<form action={updateUserWithId}>
<input type="text" name="name" />
<button type="submit">Update User Name</button>
</form>
)
}

然后,除了表单数据之外,updateUser 服务器操作将始终接收 userId 参数:

And then, the updateUser Server Action will always receive the userId argument, in addition to the form data:

'use server'

export async function updateUser(userId, formData) {
// ...
}

很高兴知道: 服务器操作的 .bind 在服务器和客户端组件中均有效。 它还支持 渐进增强

祈求

你可以使用以下方法调用服务器操作:

You can invoke Server Actions using the following methods:

  • 使用 action: React 的 action 属性允许在 <form> 元素上调用服务器操作。
  • 使用 formAction: React 的 formAction 属性允许处理 <form> 中的 <button><input type="submit"><input type="image"> 元素。
  • 使用 startTransition 进行自定义调用: 使用 startTransition 调用服务器操作而不使用 actionformAction。 此方法 禁用 渐进增强

渐进增强

渐进增强功能允许 <form> 在没有 JavaScript 的情况下或在禁用 JavaScript 的情况下正常运行。 这允许用户与表单交互并提交数据,即使表单的 JavaScript 尚未加载或加载失败。

Progressive enhancement allows a <form> to function properly without JavaScript, or with JavaScript disabled. This allows users to interact with the form and submit data even if the JavaScript for the form hasn't been loaded yet or if it fails to load.

React Actions(服务器和客户端)支持渐进增强,使用以下两种策略之一:

React Actions (both server and client) support progressive enhancement, using one of two strategies:

  • 如果将 服务器动作 直接传递给 <form>,则该形式是交互式 即使 JavaScript 被禁用
  • 如果将 客户行动 传递给 <form>,则表单仍然是交互式的,但操作将被放置在队列中,直到表单水合为止。 React 会优先考虑操作,因此它仍然会很快发生。

在这两种情况下,该形式在水合发生之前都是交互的。 尽管服务器操作具有不依赖客户端 JavaScript 的额外优势,但你仍然可以在需要时使用客户端操作编写其他行为,而无需牺牲交互性。

In both cases, the form is interactive before hydration occurs. Although Server Actions have the additional benefit of not relying on client JavaScript, you can still compose additional behavior with Client Actions where desired without sacrificing interactivity.

尺寸限制

默认情况下,发送给 Server Action 的请求体的最大大小为 1MB,以防止解析大量数据时消耗过多的服务器资源。

By default, the maximum size of the request body sent to a Server Action is 1MB, to prevent the consumption of excessive server resources in parsing large amounts of data.

但是,你可以使用 serverActions.bodySizeLimit 选项配置此限制。 它可以采用字节数或字节支持的任何字符串格式,例如 1000'500kb''3mb'

However, you can configure this limit using the serverActions.bodySizeLimit option. It can take the number of bytes or any string format supported by bytes, for example 1000, '500kb' or '3mb'.

module.exports = {
experimental: {
serverActions: {
bodySizeLimit: '2mb',
},
},
}

其他资源

目前正在记录以下 React API 页面:

The following React API pages are currently being documented: