react-hook-form中useFieldArray新增字段值重复异常原因解析
React Hook Form中useFieldArray的append/remove值残留问题解析
我在React Hook Form里用useForm和useFieldArray实现表单,把新增用户的初始值name和age设为undefined。但删除某个用户后再调用append添加新用户时,发现新用户的name和age不是预期的undefined,而是保留了之前被删除用户的值。把初始值改成null就正常了,想搞懂这个现象的内部逻辑,以及undefined会不会被默认值覆盖。
代码示例
import { uniqueId } from "lodash" import { Controller, useFieldArray, useForm } from "react-hook-form" // 预期新增值为undefined const initialState = () => ({ id: uniqueId(), name: undefined, age: undefined }) const ReactHookForm = () => { const users = [ { id: "1", name: "test1", age: 4, }, { id: "2", name: "test2", age: 5, }, ] const { control, handleSubmit } = useForm({ defaultValues: { users } }) const { fields, append, remove } = useFieldArray({ control, name: "users" }) return ( <form className="mx-auto w-[50%]" onSubmit={handleSubmit((users) => console.log(users))}> <h1>RHF</h1> <button className="bg-[blue] text-[white]" type="button" onClick={() => append(initialState())}> append </button> {fields.map((user, i) => ( <div key={user.id} className="mb-4 bg-white"> <button className="bg-[red] text-[white]" type="button" onClick={() => remove(i)}> remove </button> <Controller control={control} name={`users.${i}.name`} render={({ field: { value, onChange } }) => ( <div> <label className="w-[30%]">name</label> <input className="w-[70%]" type="text" value={value} onChange={onChange} /> </div> )} /> <Controller control={control} name={`users.${i}.age`} render={({ field: { value, onChange } }) => ( <div> <label className="w-[30%]">age</label> <input className="w-[70%]" type="number" value={value} onChange={onChange} /> </div> )} /> </div> ))} </form> ) } export default ReactHookForm
现象内部逻辑
React Hook Form的useFieldArray在处理字段数组时,是基于当前表单状态来合并新字段值的,而非完全替换。这里的核心是RHF对undefined的特殊处理逻辑:
- 当你给
append传的对象里包含undefined属性时,RHF会判定这些属性为「未定义」,不会主动覆盖表单内部对应路径已存在的值。 - 删除用户后,表单状态里并没有彻底清除该索引位置的旧值缓存。当你再次
append时,新对象里的undefined属性会被跳过,RHF直接复用之前该位置残留的旧值,导致看起来像是保留了删除用户的数据。
而null会被RHF视为明确的有效值,传入append时会主动覆盖对应位置的状态值,所以不会出现残留问题。
undefined的覆盖规则
在React Hook Form里:
undefined不会被当作有效的默认值来覆盖现有状态,RHF会跳过对undefined属性的赋值操作,保留当前状态中已有的值。- 只有传入
null、字符串、数字这类明确的有效值时,才会覆盖表单状态里的对应字段。
如果要避免这个问题,除了把初始值改成null,也可以确保新增对象的属性使用明确的有效值,而非undefined。
内容的提问来源于stack exchange,提问作者nnst0knnt
相关产品推荐
相关产品推荐

