You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击按钮后对象属性丢失问题求助(基于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的内部处理逻辑:

  1. react-hook-form默认只会跟踪通过register或registerState注册过的字段,你只注册了person.firstName和person.lastName,person.sex未被注册,不在表单的跟踪列表中。
  2. 调用setValues时,react-hook-form默认会根据跟踪列表处理字段,而mui-react-hook-form-plus的registerState内部包含了空值自动卸载字段的逻辑——当你传入空字符串给已注册的firstName和lastName时,触发了字段卸载,导致这两个属性从表单状态中被移除,未注册的sex因为不受跟踪反而被保留了下来。

解决办法

有三种可行的解决方式:

  1. 修改setValues参数,禁用自动卸载
    在调用setValues时添加shouldUnregister: false选项,强制保留所有字段:

    const update = () => {
      const data = {
        person: { firstName: "", lastName: "", sex: "Male" },
      };
      setValues(data, { shouldUnregister: false });
    };
    
  2. 注册所有需要保留的字段
    哪怕不渲染sex对应的组件,也通过registerState注册该字段,让react-hook-form跟踪它:

    // 在组件中添加这一行
    registerState("person.sex");
    
  3. 改用setValue逐个设置字段
    避免直接替换整个对象,而是逐个设置每个字段的值:

    const update = () => {
      setValue("person.firstName", "");
      setValue("person.lastName", "");
      setValue("person.sex", "Male");
    };
    

内容的提问来源于stack exchange,提问作者user5711656

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:46:12