react-hook-form Array Fields中react-select点击remove后选中值丢失
react-hook-form + react-select 移除行后选中值清空问题修复
核心原因
你代码里犯了两个关键错误:
- 直接用
watch返回的原始值绑定react-select的value,但react-select需要的是完整的选项对象,不是字符串/数值类型的原始值; - 没有用
Controller包裹react-select,而是直接用register处理受控组件,导致react-hook-form无法正确同步表单状态和组件选中状态。当调用remove删除行后,数组重新渲染,watch返回的原始值无法匹配选项列表,所有选中状态丢失。
修复方案
1. 用Controller替代register管理react-select
Controller是react-hook-form专门为受控组件设计的包装器,能正确同步表单状态和组件的value/onChange。
2. 正确转换表单值为react-select需要的选项对象
通过options.find()把表单中存储的原始值(比如"1")转换成对应的选项对象(比如{value: "1", label: "Option 1"}),确保react-select能识别选中项。
修复后的关键代码
import { useForm, Controller, useFieldArray } from "react-hook-form"; import Select from "react-select"; // 选项列表 const options = [ { value: "1", label: "Option 1" }, { value: "2", label: "Option 2" }, { value: "3", label: "Option 3" } ]; function App() { const { control, handleSubmit } = useForm({ defaultValues: { test: [{ select: "" }] } }); const { fields, append, remove } = useFieldArray({ control, name: "test" }); const onSubmit = (data) => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> {fields.map((item, index) => ( <div key={item.id}> <Controller name={`test[${index}].select`} control={control} render={({ field: { onChange, value } }) => ( <Select options={options} onChange={onChange} value={options.find(opt => opt.value === value) || null} /> )} /> <button type="button" onClick={() => remove(index)}>删除</button> </div> ))} <button type="button" onClick={() => append({ select: "" })}>添加行</button> <input type="submit" /> </form> ); } export default App;
为什么这样有效?
Controller自动处理表单状态的同步,避免手动绑定watch带来的状态不一致问题;- 通过
options.find()确保react-select始终能拿到匹配的选项对象,即使数组因remove操作重新渲染,选中状态也能正确保留。
内容的提问来源于stack exchange,提问作者yeln
相关产品推荐
相关产品推荐

