useFieldArray结合Controller时默认值异常问题排查与解决
问题原因与解决方案
这个问题我之前也碰到过,核心是对react-hook-form的Controller受控逻辑和useFieldArray的append默认行为理解不到位,下面给你拆解原因和解决办法:
一、问题根源
Controller的受控属性误用
你在Controller的render回调里给input用了defaultValue,但Controller是受控组件,应该用value来绑定表单状态。defaultValue属于非受控属性,只会在组件首次渲染时生效,后续表单状态更新时无法同步,这会导致字段值和表单内部状态脱节,尤其是在删除所有字段后append新项时,会复用初始渲染的defaultValue。useFieldArray的append默认逻辑
当你调用append()不传参数时,react-hook-form会自动从useForm的defaultValues中对应数组的第一个项提取默认值。你的初始test数组包含两个带name默认值的对象,所以删除所有项后append,它会复用这个预设的默认值,而不是生成空白项。
二、解决方法
方法1:修正Controller的受控绑定
把input的defaultValue改成value,确保它和表单状态完全同步,同时处理value为undefined的情况:
<Controller name={`test[${index}].name`} control={control} render={({value, onChange}) => <input onChange={onChange} value={value || ''} />} />
方法2:append时显式传入空白默认值
调用append时主动传入一个空白对象,覆盖默认的取值逻辑,这样每次新增的字段都会是空白状态:
<button type="button" onClick={() => append({ name: '' })}> Add </button>
方法3:(可选)调整initialValues的默认项
如果你希望append的默认行为就是生成空白项,可以调整defaultValues的数组默认项,比如初始数组为空,或者把默认项设置为空白:
// 初始数组为空,后续append空白项 const defaultValues = { test: [] };
修正后的完整示例代码
import { useForm, Controller, useFieldArray } from "react-hook-form"; export default function FieldArray() { const defaultValues = { test: [ { name: "useFieldArray1" }, { name: "useFieldArray2" } ] }; const { control } = useForm({ defaultValues }); const { fields, append, remove } = useFieldArray({ control, name: "test" }); return ( <div> <ul> {fields.map((item, index) => ( <li key={item.id}> <Controller name={`test[${index}].name`} control={control} render={({value, onChange}) => ( <input onChange={onChange} value={value || ''} /> )} /> <button type="button" onClick={() => remove(index)}> Delete </button> </li> ))} </ul> <button type="button" onClick={() => append({ name: '' })}> Add </button> </div> ); }
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

