← [ BACK_TO_NOTES ]

Next.js 表单验证与 useActionState

在 Next.js Server Action 表单中,用 FormData 接收不可信输入、运行时 Schema 验证,再用 useActionState 把 validation/result/pending 状态反馈给客户端 UI。

#concept #growing #frame #react

[!info] related notes

Next.js 表单验证与 useActionState

一句话定义

Next.js 表单 Mutation 可以让 <form action={...}> 把 FormData 交给 Server Action;服务端先做运行时验证与授权,再把结构化结果返回给 useActionState,由客户端呈现 pending、字段错误和成功状态。

完整链路

<form>
→ FormData
→ Server Action
→ runtime validation
→ authentication / authorization
→ business rule
→ durable mutation
→ structured result
→ useActionState
→ error / pending / success UI

核心不是某个 Hook,而是让 不可信输入 → 可信业务输入 → 权威写入 → 可观察 UI 状态 形成一条完整链。

FormData 是输入载体,不是可信 DTO

浏览器提交的字段即使来自:

<input type="number" name="amount" />

服务端拿到的仍可能是字符串、缺失值或恶意构造值。

因此:

FormData
≠ trusted domain input

应该先转换并验证,例如使用 Zod:

const result = Schema.safeParse({
  title: formData.get('title'),
})

if (!result.success) {
  return {
    ok: false,
    fieldErrors: result.error.flatten().fieldErrors,
  }
}

Validation、Authorization 与 Business Rule 是三层不同判断

Validation
→ 数据长得对不对?

Authentication / Authorization
→ 你是谁?你有资格操作这个资源吗?

Business Rule
→ 当前业务状态允不允许这么做?

例如合法 UUID 只证明格式正确,不能证明 Task 存在、属于当前用户或当前状态允许完成。

useActionState 管理什么

典型接口:

const [state, formAction, isPending] =
  useActionState(action, initialState)

它把一次 Action 的结果和 pending 状态暴露给 UI。

配合后,Action 的典型签名会变成:

async function action(
  previousState: State,
  formData: FormData,
): Promise<State> {
  // ...
}

previousState 是 React 管理的上一次 Action 结果,不是服务端数据库真值。

Expected Failure 与 Exception

表单校验失败、资源不存在、无权限、业务冲突通常属于可预期分支,更适合返回稳定的结构化 Result:

type Result =
  | { ok: true; id: string }
  | { ok: false; code: 'VALIDATION' | 'FORBIDDEN' | 'CONFLICT' }

数据库连接崩溃、程序 invariant 被破坏等不可预期问题,才更接近异常 / error boundary 的职责。

Pending 不是装饰动画

isPending 表示 Mutation 尚未得到确定结果,它影响:

  • 是否禁用重复提交
  • 是否显示提交中状态
  • 是否允许某些交互继续
  • 是否需要 optimistic state

因此 Pending 是 Mutation lifecycle 的正式状态,而不仅是 Spinner。

与 Optimistic UI 的关系

useActionState 与 optimistic state 解决的问题不同:

useActionState
→ 追踪 Action 的真实返回结果与 pending

optimistic UI
→ 在服务器确认前先显示预测状态

服务器失败时撤销预测叫 rollback;服务器成功但返回了真实 ID、时间戳等字段时,用权威结果替换临时对象属于 reconciliation,而不是 rollback。

最重要的边界

Server Action 在服务器运行
≠ 参数可信

Zod 验证通过
≠ Mutation 已被授权

UI 显示成功
≠ durable state 已经成功写入

服务端仍是最终业务状态 authority。

课程位置

对应 Full Stack Open Part 14 中的:

  • Validations in blog creation
  • Blog creation form on error
  • Validations in user registration
  • Returning validation errors with useActionState

并与 Next.js Server Actions、Mutation(状态变更操作) 共同构成表单写操作主线。

创建于 2026/9/16 更新于 2026/9/16
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本