如何利用enableReinitialize在Formik中重置表单?遇重置失效问题
Formik表单取消后未重置?聊聊
enableReinitialize的正确打开方式 嘿,我来帮你捋清楚这个Formik的问题~ 你遇到的场景很典型:编辑表单输入内容后点取消,再次打开表单却还留着之前输入的值,明明想着用enableReinitialize自动重置,结果没生效对吧?
先还原下你的问题场景
- 点击「编辑」按钮打开表单进入编辑状态
- 在输入框里填了内容后,点击「取消」关闭表单
- 再次点「编辑」打开表单,预期表单回到初始状态,结果却保留了之前输入的内容
- 你知道可以手动调用
resetForm()解决,但想搞懂为什么enableReinitialize没起到作用
为什么enableReinitialize没生效?
先明确官方对这个属性的定义:
enableReinitialize?: boolean,默认值为false,控制当包裹组件的props变化时Formik是否重置表单(使用深度相等判断)
划重点:只有当Formik接收的initialValues这个props发生了「深度变化」时,enableReinitialize才会触发表单重置。如果你的场景里满足以下任一情况,它就不会生效:
- 点击取消后,父组件里的
initialValues根本没更新,再次打开表单时传递的还是同一个值(甚至是同一个对象引用) - 表单只是被隐藏(比如用
display: none),Formik实例没被销毁,之前的表单状态被保留了下来
举个常见的错误例子:你可能在第一次打开表单时把原始数据传给了initialValues,但取消后没重置这个原始数据的状态,再次打开时initialValues和之前完全一样,Formik对比后认为没必要重置。
两种靠谱的解决办法
方法1:让enableReinitialize真正生效
要让它触发,就得确保每次打开表单时,传递给Formik的initialValues是全新的、和之前深度不等的值:
- 点击「编辑」按钮时,重新获取/初始化原始数据(比如从后端拉取,或者从父组件的原始状态里拷贝一份新对象)
- 用浅拷贝(比如
{...originalData})或者深拷贝(复杂对象用JSON.parse(JSON.stringify(originalData)))确保initialValues的引用发生变化 - 给Formik组件加上
enableReinitialize={true}
示例代码片段:
// 父组件里管理编辑状态和初始值 const [isEditing, setIsEditing] = useState(false); const [formInitialValues, setFormInitialValues] = useState({ name: '' }); const handleEdit = () => { // 每次编辑时都重新设置初始值,用浅拷贝生成新对象 const originalData = { name: '默认名称' }; setFormInitialValues({ ...originalData }); setIsEditing(true); }; const handleCancel = () => { setIsEditing(false); }; // Formik组件配置 <Formik initialValues={formInitialValues} enableReinitialize={true} onSubmit={(values) => { /* 提交逻辑 */ }} > {/* 你的表单输入组件 */} </Formik>
方法2:点击取消时手动调用resetForm()
如果不想折腾initialValues的变化,直接在取消按钮的点击事件里调用Formik的resetForm方法更直接,能确保即时重置:
<Formik initialValues={{ name: '' }} onSubmit={(values) => { /* 提交逻辑 */ }} > {({ resetForm }) => ( <Form> <input name="name" type="text" /> <button type="button" onClick={() => { resetForm(); // 先重置表单 setIsEditing(false); // 再关闭表单 }}>取消</button> </Form> )} </Formik>
这种方式不需要依赖initialValues的变化,适合取消按钮这种明确需要重置的场景,可靠性拉满。
最后总结一下
enableReinitialize的触发前提是initialValues发生深度变化,没满足这个条件它就不会干活- 手动调用
resetForm()是更直接的即时重置方案,适合取消、重置这类明确操作
内容的提问来源于stack exchange,提问作者Jeff Gao
相关产品推荐
相关产品推荐

