react-hook-form的默认值未在React JS中设置输入字段的值

42

我想使用react-hook-form在输入字段中提供默认值。 首先,我从API端点检索用户数据,然后将状态users设置为该用户数据。 然后,我将状态users传递给useForm()defaultValues参数。

import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import axios from "axios";

function LoginFile() {
  const [users, setUsers] = useState(null);

  useEffect(() => {
    axios
      .get("http://localhost:4000/users/1")
      .then((res) => setUsers(res.data));
  }, []);

  useEffect(() => {
    console.log(users);
  }, [users]);

  const { register, handleSubmit, errors } = useForm({
    defaultValues: users,
  });
 return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        Email <input type="email" name="email" ref={register} /><br />
        firstname <input name="firstname" ref={register} /><br/>
        <input type="submit" />
      </form>
    </div>
 );
}
export default LoginFile;

我按照上述代码操作,但是并没有像预期的那样生效。所有的输入字段仍然是空的。我想让表单输入字段有一些默认值。

2个回答

80
问题在于,在第一次渲染期间,usersuseState钩子的初始值,即null。该值只有在axios.get()请求完成后才会更改,也就是说在初始渲染之后。这意味着传递给useForm的默认值是null

defaultValues的文档中指出:

defaultValues在自定义钩子内在第一次渲染时缓存。如果要重置defaultValues,应使用reset api。

因此,您只需要使用reset手动将表单重置为您获取的值即可。 reset的文档如下:

您需要传递defaultValuesuseFormreset Controller组件的值。

但是,从文档中不清楚是否null足够作为defaultValues,或者您是否需要传递一个包含每个输入字段的正确对象。为了安全起见,让我们假设是后者。

完成此操作的代码将类似于:

function LoginFile() {
  const [users, setUsers] = useState({ email: "", firstname: "" });

  const { register, handleSubmit, errors, reset } = useForm({
    defaultValues: users,
  });

  useEffect(() => {
    axios.get("http://localhost:4000/users/1").then((res) => {
      setUsers(res.data);
      reset(res.data);
    });
  }, [reset]);

  useEffect(() => {
    console.log(users);
  }, [users]);

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        Email <input type="email" name="email" ref={register} />
        <br />
        firstname <input name="firstname" ref={register} />
        <br />
        <input type="submit" />
      </form>
    </div>
  );
}

此外,如果只是为了存储 defaultValues 的值才使用 useState 钩子,那么你根本不需要它,可以将代码整理成如下形式:

function LoginFile() {
  const { register, handleSubmit, errors, reset } = useForm({
    defaultValues: { email: "", firstname: "" },
  });

  useEffect(() => {
    axios.get("http://localhost:4000/users/1").then((res) => {
      reset(res.data);
    });
  }, [reset]);

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        Email <input type="email" name="email" ref={register} />
        <br />
        firstname <input name="firstname" ref={register} />
        <br />
        <input type="submit" />
      </form>
    </div>
  );
}

1
reset(res.data)会将defaultValue重置为API用户数据,例如{email: "subro@gg.com", firstname: "subrato"}吗?我问这个问题是因为我的想法是reset意味着清空输入字段。 - Subrato Pattanaik
2
reset 的文档中写道:“您可以将值作为可选参数传递以将表单重置为分配的默认值。” - cbr
我的用户数据中有一个“id”键。当我们在useForm中定义它们时,id的defaultValue将是什么?使用{id: 0, email; "", firstname:""}这个默认值可以吗?我正在使用您的第一种方法。 - Subrato Pattanaik
是的,这个可以工作。我注意到一件事情,想要分享一下:当我将状态设置为 null 时,它会显示一个错误,例如 无法读取空值 "email",但是当我将状态设置为 [] 时,它会在输入字段中显示空值。 - Subrato Pattanaik
1
@cbr 谢谢你,你是救星。 - Gael Musi

14

这绝对有效。使用reset API和useEffect。

将空字符串作为默认值开始,并将其作为效果与reset一起更新。以下是我的代码。这里也使用了TypeScript和Ionic...

const { control: editControl, handleSubmit: editSubmit, reset } = useForm<EditFormType>({
      defaultValues: {
         question: "",
         optionA: "",
         optionB: "",
         optionC: "",
         optionD: "",
      }
   });

   useEffect(() => {
      let defaults ={
         question: editQuestion?.body,
         optionA: editQuestion?.options[0].body,
         optionB: editQuestion?.options[1].body,
         optionC: editQuestion?.options[2].body,
         optionD: editQuestion?.options[3].body,
      }
      reset(defaults)
   }, [editQuestion, reset])


3
这个答案更容易理解,因为它没有其他答案中的所有额外干扰。 - reggaeguitar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接