表单提交状态
useFormStatus 读取哪一个表单?
- 最近祖先: 在 form 内的子组件调用 useFormStatus,读取最近父表单的提交状态,而不是组件自己返回的 form;
- 必须下移: 如果 Hook 与 form 标签在同一组件函数里,Hook 不会读取那个尚未成为祖先的标签,需提取 SubmitButton 等子组件;
- 角色区别: 此 Hook 观察表单状态,不管理操作返回值,结果状态由 useActionState 等负责;
import { useFormStatus } from "react-dom";
function SubmitButton() {
const { pending } = useFormStatus();
return <button disabled={pending}>{pending ? "正在提交" : "提交"}</button>;
}
function Form({ submit }) {
return (
<form action={submit}>
<input name="message" />
<SubmitButton />
</form>
);
}
返回对象中的字段分别代表什么?
| 字段 | 含义 |
|---|---|
| pending | 父表单是否正在提交 |
| data | 本次提交的 FormData,无提交时为 null |
| method | 本次提交采用的 get 或 post |
| action | 传入的函数 action;URL action 或无对应提交时可为 null |
如何在提交期间展示用户正在提交的内容?
- 提交快照: 从 data.get('字段名') 读取这一次提交数据,可以与用户随后修改的输入值区分;
- 空值处理: 尚未提交时 data 为 null,读取前使用可选链或条件判断;
- 范围限制: 不会追踪另一个兄弟 form,也不会因为任意点击处理器里发了 fetch 就变成 pending;
function SubmissionPreview() {
const { pending, data } = useFormStatus();
if (!pending) return null;
const message = String(data?.get("message") ?? "");
return <p aria-live="polite">正在发送:{message}</p>;
}
- 放置位置: 将 SubmissionPreview 放在提交 message 字段的 form 内,它显示提交快照,而非另一份独立输入状态;