React中Formik更新数组值后表单始终不处于dirty状态
解决Formik中复选框数组修改后
dirty状态始终为false的问题 问题根源
你遇到的dirty始终为false,是因为初始化Formik时,initialValues直接引用了外部的options数组。后续修改复选框状态时,你只是浅拷贝了数组,但数组内的对象还是和initialValues里的对象共享引用,导致修改checked属性时,initialValues里的对应对象也被意外改变。Formik比较当前值与初始值时,认为两者完全一致,所以dirty一直是false。
解决方案
1. 独立初始化initialValues
初始化时对options数组里的每个对象进行浅拷贝,确保initialValues的对象拥有独立引用,不会被后续修改影响:
initialValues={{ checkboxValues: options.map(opt => ({ ...opt })) }}
2. 规范不可变更新逻辑(可选)
修改复选框状态时,创建新的对象而非直接修改原对象,避免意外的引用修改,让状态更新更符合React的不可变原则:
onClick={() => { const updatedOptions = values.checkboxValues.map((opt, index) => index === i ? { ...opt, checked: !opt.checked } : opt ); setFieldValue("checkboxValues", updatedOptions); }}
修改后的完整代码
import { Formik, Form } from "formik"; const Checkbox = ({ label, onClick, checked }) => { return <div onClick={onClick}>{label}: {JSON.stringify(checked)}</div>; }; const options = [{ value: "first", checked: false }, { value: "second", checked: true }]; export default function App() { return ( <Formik initialValues={{ checkboxValues: options.map(opt => ({ ...opt })) }} onSubmit={(values) => {console.log(values)}} > {({ values, dirty, setFieldValue }) => ( <Form> {values.checkboxValues.map((v, i) => { return ( <Checkbox key={v.value} label={v.value} checked={v.checked} onClick={() => { const updatedOptions = values.checkboxValues.map((opt, index) => index === i ? { ...opt, checked: !opt.checked } : opt ); setFieldValue("checkboxValues", updatedOptions); }} /> ); })} <button type="submit">submit</button> {dirty ? <p>dirty</p> : <p>clean</p>} </Form> )} </Formik> ); }
内容的提问来源于stack exchange,提问作者axtck
相关产品推荐
相关产品推荐

