使用Formik的FieldArray组件搭配select时出现key错误该如何解决
Formik多组select字段渲染Key错误修复方案
问题根因
该问题的核心触发原因是列表渲染时使用了数组的index作为组件的key属性值。在动态列表渲染场景下,key必须是和元素绑定的唯一稳定值,不能用可变的索引作为key。当删除数组靠前位置的条目后,后续所有条目的索引会整体前移,React的Diff算法无法识别每个表单组的唯一身份,会错误复用原有组件实例,导致Formik的字段状态绑定错位,最终出现非预期的新增条目以及控制台报错。
修复步骤
- 给每个表单条目新增唯一稳定标识
每个新增的收入条目都新增一个和用户输入无关的唯一字段id,可以用Date.now()或者轻量uuid生成逻辑生成,确保不同条目的id不会重复。
// 新增条目逻辑调整 const addIncomeItem = () => { setFieldValue('incomeList', [ ...values.incomeList, { type: '', amount: '', id: Date.now() // 新增唯一id字段 } ]) }
- 替换列表渲染的key值
将原来渲染列表时用的key={index}替换为key={item.id},保证每个表单组的key在数组顺序变化时保持稳定。
// 列表渲染逻辑调整 {values.incomeList.map((item, index) => ( <div key={item.id}> {/* 唯一稳定key */} <select name={`incomeList[${index}].type`} onChange={handleChange} value={values.incomeList[index].type} /> {/* 其他表单字段 */} </div> ))}
- 调整删除条目的逻辑
删除条目时按照id过滤数组,而非按照索引删除,避免其他条目的索引变化影响状态绑定。
// 删除条目逻辑调整 const removeIncomeItem = (targetId) => { setFieldValue('incomeList', values.incomeList.filter(item => item.id !== targetId)) } // 调用删除时传入当前条目的id <button onClick={() => removeIncomeItem(item.id)}>remove</button>
注意事项
- 禁止使用select选中值、输入金额等用户可修改的字段作为key,若出现重复值仍会触发key冲突问题
- 字段名
incomeList[${index}].type无需修改,只要key保持稳定,Formik会自动对应到正确的数组位置的字段状态
内容的提问来源于stack exchange,提问作者vinkovsky
相关产品推荐
相关产品推荐

