服务器操作
服务器操作允许客户端组件调用在服务器上执行的异步函数。
- 从服务器组件创建服务器操作
- 从客户端组件导入服务器操作
- 使用 Actions 组合服务器操作
- 使用服务器操作的表单操作
- 使用
useActionState
的服务器操作 - 使用
useActionState
进行渐进增强
当使用 "use server"
指令定义服务器操作时,您的框架将自动创建对服务器函数的引用,并将该引用传递给客户端组件。 当在客户端调用该函数时,React 将向服务器发送请求以执行该函数,并返回结果。
可以在服务器组件中创建服务器操作,并将其作为 props 传递给客户端组件,或者可以在客户端组件中导入和使用它们。
从服务器组件创建服务器操作
服务器组件可以使用 "use server"
指令定义服务器操作
// Server Component
import Button from './Button';
function EmptyNote () {
async function createNoteAction() {
// Server Action
'use server';
await db.notes.create();
}
return <Button onClick={createNoteAction}/>;
}
当 React 渲染 EmptyNote
服务器组件时,它将创建对 createNoteAction
函数的引用,并将该引用传递给 Button
客户端组件。 当单击该按钮时,React 将使用提供的引用向服务器发送请求,以执行 createNoteAction
函数
"use client";
export default function Button({onClick}) {
console.log(onClick);
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
return <button onClick={onClick}>Create Empty Note</button>
}
有关更多信息,请参阅 "use server"
的文档。
从客户端组件导入服务器操作
客户端组件可以从使用 "use server"
指令的文件中导入服务器操作
"use server";
export async function createNoteAction() {
await db.notes.create();
}
当捆绑器构建 EmptyNote
客户端组件时,它将在捆绑包中创建对 createNoteAction
函数的引用。 当单击 button
时,React 将使用提供的引用向服务器发送请求,以执行 createNoteAction
函数
"use client";
import {createNoteAction} from './actions';
function EmptyNote() {
console.log(createNoteAction);
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
<button onClick={createNoteAction} />
}
有关更多信息,请参阅 "use server"
的文档。
使用 Actions 组合服务器操作
服务器操作可以与客户端上的 Actions 组合
"use server";
export async function updateName(name) {
if (!name) {
return {error: 'Name is required'};
}
await db.users.updateName(name);
}
"use client";
import {updateName} from './actions';
function UpdateName() {
const [name, setName] = useState('');
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const submitAction = async () => {
startTransition(async () => {
const {error} = await updateName(name);
if (!error) {
setError(error);
} else {
setName('');
}
})
}
return (
<form action={submitAction}>
<input type="text" name="name" disabled={isPending}/>
{state.error && <span>Failed: {state.error}</span>}
</form>
)
}
这允许您通过将服务器操作包装在客户端上的 Action 中来访问服务器操作的 isPending
状态。
有关更多信息,请参阅 在 <form>
之外调用服务器操作 的文档
使用服务器操作的表单操作
服务器操作适用于 React 19 中的新表单功能。
您可以将服务器操作传递给表单,以自动将表单提交到服务器
"use client";
import {updateName} from './actions';
function UpdateName() {
return (
<form action={updateName}>
<input type="text" name="name" />
</form>
)
}
当表单提交成功时,React 将自动重置表单。 您可以添加 useActionState
来访问挂起状态、最后响应或支持渐进增强。
有关更多信息,请参阅 表单中的服务器操作 的文档。
使用 useActionState
的服务器操作
对于只需要访问操作待处理状态和上次返回的响应的常见情况,您可以使用 useActionState
来组合服务器操作
"use client";
import {updateName} from './actions';
function UpdateName() {
const [state, submitAction, isPending] = useActionState(updateName, {error: null});
return (
<form action={submitAction}>
<input type="text" name="name" disabled={isPending}/>
{state.error && <span>Failed: {state.error}</span>}
</form>
);
}
在使用服务器操作时,如果使用 useActionState
,React 还会自动重放 hydration 完成之前输入的表单提交内容。这意味着用户甚至可以在应用完成 hydration 之前就与您的应用进行交互。
有关详细信息,请参阅 useActionState
的文档。
使用 useActionState
进行渐进增强
服务器操作还支持使用 useActionState
的第三个参数进行渐进增强。
"use client";
import {updateName} from './actions';
function UpdateName() {
const [, submitAction] = useActionState(updateName, null, `/name/update`);
return (
<form action={submitAction}>
...
</form>
);
}
如果在 JavaScript 包加载之前提交了表单,当 permalink 提供给 useActionState
时,React 将重定向到提供的 URL。
有关详细信息,请参阅 useActionState
的文档。