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

2 min read 06-10-2024
How to change React-Hook-Form defaultValue with useEffect()?


Dynamic Default Values in React Hook Form with useEffect

React Hook Form is a powerful library for managing form state and validation in React applications. But sometimes, you need your form fields to have default values that change dynamically based on external data or user interactions. This is where useEffect comes in handy.

Let's imagine a scenario where you have a form to edit a user's profile. The initial values of the form should be fetched from the user's data, which is loaded asynchronously. Here's an example of how you might approach this:

import { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';

function UserProfileForm() {
  const [userData, setUserData] = useState(null);
  const { register, handleSubmit, setValue } = useForm();

  useEffect(() => {
    // Fetch user data from an API or another source
    fetch('/api/users/current')
      .then(res => res.json())
      .then(data => setUserData(data));
  }, []);

  if (!userData) {
    return <div>Loading user data...</div>;
  }

  const onSubmit = (data) => {
    // Handle form submission here
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="name">Name:</label>
        <input type="text" {...register('name')} defaultValue={userData.name} />
      </div>
      <div>
        <label htmlFor="email">Email:</label>
        <input type="email" {...register('email')} defaultValue={userData.email} />
      </div>
      <button type="submit">Save</button>
    </form>
  );
}

export default UserProfileForm;

In this example, we fetch user data using useEffect and store it in the userData state. Once the data is loaded, we use defaultValue to populate the form fields with the retrieved information.

Why not directly set defaultValue within useEffect?

While it's tempting to set defaultValue directly inside useEffect, this approach has limitations:

  • React Hook Form updates: defaultValue is only used for the initial rendering of the form. Subsequent changes in the userData state won't automatically update the form fields.
  • Performance impact: Repeatedly setting defaultValue within useEffect can lead to unnecessary re-renders and impact performance, especially for larger forms with frequent data updates.

The setValue solution:

Instead of relying on defaultValue, the recommended approach is to utilize setValue from React Hook Form. setValue allows you to dynamically change the values of form fields after the initial rendering:

import { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';

function UserProfileForm() {
  const [userData, setUserData] = useState(null);
  const { register, handleSubmit, setValue } = useForm();

  useEffect(() => {
    fetch('/api/users/current')
      .then(res => res.json())
      .then(data => {
        setUserData(data);
        // Set default values for each field using setValue
        setValue('name', data.name);
        setValue('email', data.email);
      });
  }, []);

  if (!userData) {
    return <div>Loading user data...</div>;
  }

  const onSubmit = (data) => {
    // Handle form submission here
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="name">Name:</label>
        <input type="text" {...register('name')} />
      </div>
      <div>
        <label htmlFor="email">Email:</label>
        <input type="email" {...register('email')} />
      </div>
      <button type="submit">Save</button>
    </form>
  );
}

export default UserProfileForm;

This approach ensures that:

  • Form fields are updated correctly: setValue updates the form's internal state, ensuring that all subsequent renders reflect the latest data.
  • Optimized performance: setValue is designed to efficiently update the form state without unnecessary re-renders.

By combining useEffect and setValue, you can create dynamic forms in React Hook Form that seamlessly adapt to changing data, enhancing the user experience and keeping your code clean and efficient.