485 字
2 分钟
useFormStatus

它读的是父级表单的提交状态
import { useFormStatus } from 'react-dom'
function Submit() { const { pending } = useFormStatus()
return ( <button type="submit" disabled={pending}> {pending ? '提交中……' : '提交'} </button> )}
export default function Form() { return ( <form action={submitForm}> <input name="email" /> <Submit /> </form> )}导入来源是 react-dom,不是 react,这一点和别的 Hook 不一样。它不接受参数。
为什么必须拆成子组件
这是它最容易踩的坑:useFormStatus 只认父级 <form>,不认自己所在组件渲染出来的那个表单。
// 不行:pending 永远是 falsefunction Form() { const { pending } = useFormStatus()
return ( <form action={submit}> <button disabled={pending}>提交</button> </form> )}同一个组件里渲染的 <form> 它看不到,子组件里的 <form> 也不看。所以提交按钮必须抽成单独的组件,放进表单内部,像上面第一个例子那样。
四个返回值
const { pending, data, method, action } = useFormStatus()pending 是布尔值,表示父级表单是否正在提交。
data 是正在提交的 FormData,没有进行中的提交(或没有父级表单)时是 null。可以用它做「正在提交 xxx」这类提示。
method 是 'get' 或 'post'。
action 指向父级表单 action 上那个函数;如果写的是 URL,或者根本没写,这里是 null。
与 useActionState 的分工
两者经常一起用,但它们站的位置不同。
useActionState 用在持有状态的那一层:拿动作的返回值、拿 isPending、决定显示什么错误。见 useActionState。
useFormStatus 用在表单内部的子组件:按钮、输入框这类只需要知道「现在能不能点」的地方。它省掉了把 isPending 一层层传下去的麻烦。
一条边界
它读的是「最近一次表单提交」的状态,不是「某个动作」的状态。同一个表单里同时发起两件互不相关的异步操作时,别指望它能分清,那种情况要给每个动作自己带状态。
useFormStatus
https://www.choria.top/posts/hook-use-form-status/分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 190 天
部分内容可能已过时