DefaultValues of react-hook-form is not setting the values to the Input fields in React JS

94.4k Views Asked by At

I want to provide default values in the input field using react-hook-form. First I retrieve the user data from the API endpoint and then setting the state users to that user data. Then I pass the state users to the defaultValues of useForm().

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;

I did by the above code but didn't work as expected. All the input fields are still empty. I want to have some default values in the input field of my form.

3

There are 3 best solutions below

6
On BEST ANSWER

The problem is that during the first render, users is the useState hook's initial value, which is null. The value only changes after the axios.get() request finishes, which is after the initial render. This means that the the default values passed to useForm is null.

The documentation for defaultValues says the following:

defaultValues are cached on the first render within the custom hook. If you want to reset the defaultValues, you should use the reset api.

So, you'll just need to use reset to reset the form manually to the values which you fetch. The documentation for reset says the following:

You will need to pass defaultValues to useForm in order to reset the Controller components' value.

However, it's unclear from the documentation whether null is enough as the defaultValues, or if you need to pass it a proper object with fields for each input. To play it safe, let's assume it's the latter.

The code for doing this would look something like this:

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>
  );
}

Additionally, if the only reason for the useState hook is to store the value for defaultValues, you don't need it at all and can clean up the code to be:

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>
  );
}
0
On

I will just explain my findings here, we must set defaultValue in order for reset to work, and also to get get correct isdirty value or to reset isDirty value when value reset to default. To set defaultValue, we have options to set defaultValue with useForm or use reset or resetField inside useEffect hook. Note- setValue will not set default value.

2
On

That definitely Worked. Using the reset API and the UseEffect.

Starting with empty stings as default values and the updating them as effects with the reset. Here is my code. Was using TypeScript with Ionic here as well...

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])