为什么需要 Server Actions?
在传统的 React 应用中,处理表单提交通常需要以下步骤:
- 在前端定义表单组件,管理表单状态。
- 编写 API 路由(如 Next.js 的 Route Handlers 或 Express 端点)。
- 在表单提交时,通过 fetch 或 axios 发送请求。
- 在服务端处理数据,并返回响应。
- 在前端处理响应,更新 UI 或显示错误。
这个过程涉及大量样板代码,而且前后端逻辑分离使得维护变得困难。React Server Actions 彻底改变了这一现状:它允许你直接在服务端组件中定义异步函数,然后在客户端组件中像调用普通函数一样调用它们。数据突变变得像调用一个本地函数一样简单,同时保持了服务端的安全性和性能优势。
基础用法:第一个 Server Action
首先,确保你的项目使用 React 19 或 Next.js 14+(App Router)。Server Actions 可以用在服务端组件中,也可以用在客户端组件中(通过 "use server" 指令)。
1. 在服务端组件中定义 Action
// app/actions.ts (Server Component)
"use server";
export async function createUser(formData: FormData) {
const name = formData.get("name") as string;
const email = formData.get("email") as string;
// 模拟数据库操作
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(`User created: ${name} (${email})`);
return { success: true, message: "User created!" };
}
> 💡 注意:"use server" 指令必须位于文件的顶部,并且只能导出异步函数。
2. 在客户端组件中使用 Action
// app/page.tsx (Client Component)
"use client";
import { createUser } from "./actions";
export default function Home() {
return (
<form action={createUser}>
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<button type="submit">Create User</button>
</form>
);
}
当表单提交时,React 会自动将 FormData 传递给 createUser 函数,并在服务端执行。整个过程无需手动发送 HTTP 请求,也无需管理加载状态。
3. 处理加载状态与表单重置
虽然 action 属性会自动处理提交,但有时我们需要在客户端显示加载状态。可以使用 useFormStatus 钩子:
// app/SubmitButton.tsx
"use client";
import { useFormStatus } from "react-dom";
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Submitting..." : "Create User"}
</button>
);
}
然后在表单中使用:
<form action={createUser}>
<input type="text" name="name" required />
<input type="email" name="email" required />
<SubmitButton />
</form>
useFormStatus 必须在表单的子组件中使用,它会自动读取最近的