点击按钮后对象属性丢失问题求助(基于mui-react-hook-form-plus)
使用mui-react-hook-form-plus时setValues导致对象属性丢失的问题
我在项目中使用了依赖react-hook-form的mui-react-hook-form-plus包,遇到点击按钮调用setValues后对象属性丢失的问题。点击按钮时的设置代码如下:
const update = () => { const data = { person: { firstName: "", lastName: "", sex: "Male" }, }; setValues(data); };
完整组件代码:
export default function App() { const defaultValues = { person: { firstName: "", lastName: "", sex: "" }, }; const methods = useHookForm<any>({ defaultValues, }); const { registerState, handleSubmit, getValues, setValues } = methods; console.log(getValues()); const onSubmit = (data: any) => { console.log(JSON.stringify(getValues(), null, 2)); }; const update = () => { const data = { person: { firstName: "", lastName: "", sex: "Male" }, }; setValues(data); }; return ( <div className="App"> <HookFormProvider {...methods}> <form onSubmit={handleSubmit(onSubmit)}> <Stack direction="row" spacing={2}> <HookTextField {...registerState("person.firstName")} textFieldProps={{ label: "First Name" }} /> <HookTextField {...registerState("person.lastName")} textFieldProps={{ label: "Last Name" }} /> </Stack> <button onClick={update}>set value</button> <br /> {JSON.stringify(getValues("person"), null, 2)} <br /> </form> </HookFormProvider> </div> ); }
复现步骤
- 运行应用,初始person对象值为
{"firstName": "", "lastName": "", "sex": ""} - 点击"set value"按钮后,person对象变为
{"sex": "Male"} - firstName和lastName属性被移除,怀疑是该包内部的form-utils.ts代码导致的。
问题原因
核心原因是react-hook-form的字段跟踪机制,结合mui-react-hook-form-plus的内部处理逻辑:
- react-hook-form默认只会跟踪通过
register或registerState注册过的字段,你只注册了person.firstName和person.lastName,person.sex未被注册,不在表单的跟踪列表中。 - 调用
setValues时,react-hook-form默认会根据跟踪列表处理字段,而mui-react-hook-form-plus的registerState内部包含了空值自动卸载字段的逻辑——当你传入空字符串给已注册的firstName和lastName时,触发了字段卸载,导致这两个属性从表单状态中被移除,未注册的sex因为不受跟踪反而被保留了下来。
解决办法
有三种可行的解决方式:
修改setValues参数,禁用自动卸载
在调用setValues时添加shouldUnregister: false选项,强制保留所有字段:const update = () => { const data = { person: { firstName: "", lastName: "", sex: "Male" }, }; setValues(data, { shouldUnregister: false }); };注册所有需要保留的字段
哪怕不渲染sex对应的组件,也通过registerState注册该字段,让react-hook-form跟踪它:// 在组件中添加这一行 registerState("person.sex");改用setValue逐个设置字段
避免直接替换整个对象,而是逐个设置每个字段的值:const update = () => { setValue("person.firstName", ""); setValue("person.lastName", ""); setValue("person.sex", "Male"); };
内容的提问来源于stack exchange,提问作者user5711656
相关产品推荐
相关产品推荐

