How to change React-Hook-Form defaultValue with useEffect()? – React-hook-form

Photo of author
Written By M Ibrahim
react-hook-form react-hooks reactjs

Quick Fix: Utilize setValue from useForm to update default values of React-Hook-Form after fetching user data. Remove default values from the form directly.

The Problem:

In React with React-Hook-Form library, a user wants to create a page for updating personal data. They want to pre-populate the form with the user’s current data, which is fetched from an API. The user has a code where they use ‘useEffect’ hook to fetch the user data and set it as the ‘defaultValue’ of the form inputs, but the values are not getting populated in the input fields.

The Solutions:

Solution 1: Using setValue()

To change the defaultValue of React-Hook-Form using useEffect(), you can use the setValue() method. Here’s how to do it:

  1. Import setValue() from useForm:
import { handleSubmit, control, setValue} from 'react-hook-form';
  1. Call setValue() with the user data after it’s received:
useEffect(() => {
    if (userData) {
        setValue([
            { name: userData.name }, 
            { phone: userData.phone }
        ]);
    }
}, [userData]);
  1. Remove the defaultValue from the form:
<Controller
    as={<input type='text' />}
    control={control}
    name='name'
/>

This should allow you to set the default values for the form fields using useEffect() and setValue().

Solution 2: Use `useForm` with `defaultValues` and `useEffect` to reset the form values

In this solution, we’ll set the default values of the form using useForm and then use useEffect to reset the form values when they change.

  • Define the default values within the useForm hook.

    const { register, reset, handleSubmit } = useForm({
        defaultValues: useMemo(() => ({
            name: props.user.name,
            phone: props.user.phone,
        }), [props])
    });
    
  • Reset the form values when the user changes using useEffect.

    useEffect(() => {
        reset(props.user);
    }, [props.user]);
    

This approach ensures that the form values are properly updated and displayed when the user’s data is fetched and changes.

Solution 3: Reset the form state using `reset`

While `setValue` might not work as expected in this context, the `reset` method provided by React-Hook-Form can be used effectively.

Here’s how you can use the `reset` method to set default values in your form after fetching data with `useEffect`:

  1. Import the useForm and reset method.

import { useForm, reset } from 'react-hook-form';
  1. Inside your functional component, define the form state and event handlers.

const { register, handleSubmit, errors } = useForm();

const onSubmit = (data) => {
  // Submit form data
};
  1. Fetch the user data using useEffect and set it to the form state using reset.
useEffect(() => {
  const account = localStorage.getItem('account');
  fetchUserData(account).then((userData) => {
    reset({
      name: userData.name,
      phone: userData.phone,
    });
  });
}, [fetchUserData]);
  1. In your form, use the register hook to register the form fields and defaultValue prop to set the initial values.

<form onSubmit={handleSubmit(onSubmit)}>
  <input {...register('name')} defaultValue={userData ? userData.name : ''} />
  <input {...register('phone')} defaultValue={userData ? userData.phone : ''} />
  <button type="submit">Submit</button>
</form>
  1. When the form is submitted, the onSubmit event handler will be triggered and you can proceed with submitting the data.

With this approach, the form fields will be pre-populated with the fetched user data after the initial API call.

Solution 4: Using `reset` API from React-Hook-Form

Here’s a more explainable and efficient way to set the default values of a React-Hook-Form with `useEffect()`:

1. Import necessary modules:

“`js
import React, { useState, useEffect } from ‘react’;
import { useForm, Controller, reset } from ‘react-hook-form’;
import { URL } from ‘../constants’;
“`

2. Define the component:

“`js
const UpdateUserData = () => {
const [userData, setUserData] = useState(null);
const { handleSubmit, control } = useForm({ mode: ‘onBlur’ });

const fetchUserData = async (account) => {
const userData = await fetch(${URL}/user/${account})
.then(res => res.json());
setUserData(userData);
};

useEffect(() => {
const account = localStorage.getItem(‘account’);
fetchUserData(account);
}, []);

const onSubmit = async (data) => {
// TODO
};

return (


<Controller
as={}
control=
name=’name’
defaultValue={userData?.name || ”}
/>

    <div>
      <label>Phone:</label>
      <Controller
        as={<input type='text' />}
        control={control}
        name='phone'
        defaultValue={userData?.phone || ''}
      />
    </div>
    <button>Submit</button>
  </form>
</div>

);
};

export default UpdateUserData;


<p>
  <b>Explanation:</b>
</p>
<ul>
  <li>
    We are using the `reset` API from React-Hook-Form to reset the form state with new data fetched from the API.
  </li>
  <li>
    The `reset` function takes an object as an argument, where the keys are the input names and the values are the corresponding values to be set.
  </li>
  <li>
    We call the `reset` function inside the `useEffect` hook after the API data has been fetched and set to the `userData` state.
  </li>
  <li>
    This ensures that the form's default values are updated with the latest data from the API.
  </li>
</ul>

Solution 5: Use the setValue method

With the help of the setValue method, you can set the default value of the input fields after the data is fetched. The setValue method takes two parameters: the name of the input field and the value you want to set. Here’s how you can use it:

useEffect(() => {
  const account = localStorage.getItem('account');
  fetchUserData(account);
}, []);

useEffect(() => {
  if (userData) {
    setValue('name', userData.name);
    setValue('phone', userData.phone);
  }
}, [userData]);

In this code, we’re using the setValue method inside a second useEffect hook to set the default values of the input fields. The first useEffect hook is used to fetch the user’s data, and the second useEffect hook is used to set the default values once the data is fetched. This ensures that the default values are set only after the data is available.