React 挂钩形式:OnSubmit 给我重置值(注册无效)

React hook form : OnSubmit give me the reseted values (register has no effect)

我有一个问题让我头疼 React Hook Form 和 Material UI。

我有一个用于创建和更新用户的表单以及使用 React Hook 表单进行验证的表单。这是我的代码:

const [user, setUser] = useState({})

const schema = yup.object().shape({
    email: yup.string().email().required("Email required"),
})

const { register, handleSubmit, reset, formState: { errors } } = useForm({
    mode: "onChange",
    reValidateMode: 'all',
    resolver: yupResolver(schema), 
    defaultValues: user
})

useEffect(() => {
    fetch(`localhost/api/user/${ route.params.userId }`).then(async r => {
        let userDatas = await r.json()
        setUser(userDatas)
    })
}, [route.params.userId])

useEffect(() => {
    if( route.params.userId && Object.keys(user).length ) {
        reset(user)
    }
}, [user])

const onSubmit = async (datas) => {
    console.log(datas)
}

const handleVerifyDuplicate = async => {
    //This function check that the email is not yet used in the database
}

return (
    <form autoComplete="off" noValidate onSubmit={handleSubmit(onSubmit)}>
        <TextField
            name="email"
            label="Email"
            margin="dense"
            variant="outlined"
            required
            { ...register("email") }
            onChange={(event) => {
                register('email').onChange(event)
                handleVerifyDuplicate(event)
            }}
            defaultValue={user && user.email}
          />
          <Button
              id="btn-save"
              variant="contained"
              color="primary"
              size="small"
              startIcon={<SaveIcon />}
              type="submit"
            >Save</Button>
    </form>
)

所以,在创作上它很有魅力,但在版本上...

如果我更改电子邮件输入,然后提交表单,console.log在onSubmit函数中给我用户邮箱的初始值,不是我刚输入的新的...

如果我去掉reset方法,之前的问题就解决了...但是如果我提交表格而不改变任何东西( onChange 未触发),它告诉我它是必需的(当作为一个版本时,该值存在于输入中但未被验证检测到)

你有解决这两个问题的方法还是我做错了什么?

感谢您的帮助

你的两个问题都是因为你没有使用 RHF 的 <Controller /> 组件:对于像 Material UI 的 [=12= 这样的外部控制组件] 你必须使用它,因为现在 RHF 没有机会 link <TextField /> 到它的形式状态,因为 register 不与外部控制组件一起工作。在文档中查看此 section 以获取更多信息。

const schema = yup.object().shape({
  email: yup.string().email().required("Email required"),
});

const {
  control,
  handleSubmit,
  reset,
  formState: { errors },
} = useForm({
  mode: "onChange",
  reValidateMode: "all",
  resolver: yupResolver(schema),
});

useEffect(() => {
  fetch(`localhost/api/user/${route.params.userId}`).then(async (r) => {
    let userDatas = await r.json();
    reset(userDatas);
  });
}, [route.params.userId]);

const onSubmit = async (datas) => {
  console.log(datas);
};

const handleVerifyDuplicate = (async) => {
  //This function check that the email is not yet used in the database
};

return (
  <form autoComplete="off" noValidate onSubmit={handleSubmit(onSubmit)}>
    <Controller
      name="email"
      control={control}
      render={({ field: { onChange, value } }) => (
        <TextField
          name="email"
          label="Email"
          margin="dense"
          variant="outlined"
          required
          value={value}
          onChange={(event) => {
            handleVerifyDuplicate(event);
            onChange(event);
          }}
        />
      )}
    />

    <Button
      id="btn-save"
      variant="contained"
      color="primary"
      size="small"
      startIcon={<SaveIcon />}
      type="submit"
    >
      Save
    </Button>
  </form>
);

我认为您也不需要第二个 useEffect,因为您可以在从 API.[=18 获取用户数据后使用 RHF reset =]