如何在Formik的FieldArray嵌套数组中实现单对象切换开关功能
解决Formik FieldArray嵌套对象开关状态不生效问题
你遇到的状态不生效问题,通常由两种原因导致:setFieldValue传入的字段路径错误,或是直接修改了Formik的状态对象导致无法触发重渲染。可以按以下方案实现:
实现步骤
1. 绑定开关的正确字段路径
FieldArray内的每个元素都对应唯一的索引路径,开关直接绑定[数组字段名].[索引].isEditing即可,Formik会自动处理状态同步,无需手动修改状态。示例代码如下:
import { Formik, Form, Field, FieldArray } from 'formik'; const initialValues = { // FieldArray对应的字段为items items: [ { name: '示例1', isEditing: false }, { name: '示例2', isEditing: false } ] }; function MyForm() { return ( <Formik initialValues={initialValues} onSubmit={values => console.log(values)}> {({ values }) => ( <Form> <FieldArray name="items"> {({ push, remove }) => ( <> {values.items.map((item, index) => ( // 建议替换为每个对象的唯一ID作为key,避免数组操作时状态错位 <div key={index}> {/* 切换开关直接绑定对应路径的isEditing */} <Field type="checkbox" name={`items.${index}.isEditing`} /> <label>开启编辑</label> {/* 输入框根据当前item的isEditing状态判断是否禁用 */} <Field name={`items.${index}.name`} disabled={!item.isEditing} placeholder="请输入内容" /> <button type="button" onClick={() => remove(index)}>删除当前项</button> </div> ))} <button type="button" onClick={() => push({ name: '', isEditing: false })} > 新增项 </button> </> )} </FieldArray> <button type="submit">提交</button> </Form> )} </Formik> ); }
2. 手动修改状态的正确写法
如果需要自定义切换逻辑,手动调用setFieldValue时必须传入完整的字段路径:
const handleToggle = (index, setFieldValue, currentStatus) => { // 传入完整路径+新值,不要直接修改values对象 setFieldValue(`items.${index}.isEditing`, !currentStatus); };
注意事项
- 禁止直接修改Formik的values对象,比如
values.items[index].isEditing = true这类直接突变的写法,Formik无法检测到状态变更,不会触发重渲染 - 如果嵌套Fields抽离为单独组件,可通过
useFormikContext钩子在子组件内获取最新的values,或直接把isEditing作为props传入子组件,确保状态能同步到子层
内容的提问来源于stack exchange,提问作者George Alexopoulos
相关产品推荐
相关产品推荐

