Creating a Dynamic Form with React Hook Form: A Step-by-Step Guide
Introduction
In the realm of modern web development, crafting interactive forms is a pivotal task. Whether it's for user registrations, data submissions, or any other input-driven interaction, forms play a pivotal role in user interfaces. Streamlining this process, the react-hook-form
library offers a powerful and developer-friendly solution. This comprehensive tutorial will walk you through the process of creating a dynamic address form utilizing the useForm
and useFieldArray
hooks, generously provided by react-hook-form
. By the end of this guide, you'll have gained a deep understanding of building adaptable forms that seamlessly integrate with the react-hook-form
library.
Unraveling react-hook-form
Before we embark on creating our dynamic address form, let's take a moment to acquaint ourselves with the essence of the react-hook-form
library. Renowned within the React developer community, this library stands as a favored solution for form management due to its emphasis on simplicity, optimal performance, and seamless integration with React's functional component model. By capitalizing on React's hooks, developers can effortlessly manage form states, validation, and submission logic through intuitive hooks-based functions. Leveraging uncontrolled components, react-hook-form
orchestrates minimal re-renders, resulting in a smooth and efficient form-building experience.
Preparing the Ground
Before delving into the nitty-gritty, ensure that your React application is up and running. If you haven't already incorporated the react-hook-form
library, initiate the process by executing the following command:
npm install react-hook-form
Constructing the Dynamic Address Form
Let's embark on the journey of creating our dynamic address form. To set the stage, we'll begin by importing the essential functions from the react-hook-form
library. Subsequently, we'll lay the foundation by structuring the initial form setup.
import { useFieldArray, useForm } from 'react-hook-form';
const App = () => {
const { register, handleSubmit, control } = useForm();
const { fields, append } = useFieldArray({
control,
name: 'addresses',
});
const onSubmit = (data) => {
console.log(data);
};
// Additional component code...
};
The code snippet above kicks off the process by importing the pivotal useForm
and useFieldArray
hooks from the react-hook-form
library. The useForm
hook empowers us to manage the form's state, while the useFieldArray
hook aids us in managing dynamic arrays of form fields.
Crafting the Form User Interface
Now, let's transition to creating the user interface for our dynamic address form using HTML and the hooks graciously bestowed upon us by the react-hook-form
library.
return (
<div className='flex items-center justify-center min-h-screen bg-gray-100'>
<form
className='w-[600px] p-8 bg-white rounded-lg shadow-lg'
onSubmit={handleSubmit(onSubmit)}
>
<h1 className='text-3xl text-center font-semibold text-gray-900 mb-6'>
Address Form
</h1>
<div className='mb-6 p-6 bg-gray-50 rounded-md shadow-md'>
{/* Personal information fields */}
</div>
{fields.map((field, index) => (
<div className='mb-6 p-6 bg-gray-50 rounded-md shadow-md' key={field.id}>
{/* Dynamic address fields */}
</div>
))}
<div className='flex items-center justify-end mt-6'>
<button
className='bg-blue-500 px-6 py-2 rounded-md text-white hover:bg-blue-600 transition duration-300'
onClick={() => append({ street: '', city: '', zip: '' })}
type='button'
>
Add Address
</button>
<button
className='bg-blue-500 ml-4 px-6 py-2 rounded-md text-white hover:bg-blue-600 transition duration-300'
type='submit'
>
Submit
</button>
</div>
</form>
</div>
);
The code segment above structures the form's visual representation:
The form begins with a div element encompassing the entire form, offering a central alignment.
The form tag carries essential attributes, such as its dimensions and submission handling via the
handleSubmit
function.A captivating h1 tag announces the purpose of the form.
Div elements are employed for personal information fields and dynamic address sections.
The
fields.map
function dynamically maps the address fields using thefields
array.A final flex container accommodates the "Add Address" and "Submit" buttons, offering responsive and engaging interactions.
Managing Dynamic Addresses
Let's delve deeper into the art of handling dynamic address fields with the useFieldArray
hook.
{fields.map((field, index) => (
<div className='mb-6 p-6 bg-gray-50 rounded-md shadow-md' key={field.id}>
<div className='flex flex-col mb-4'>
<label htmlFor={`addresses.${index}.street`} className='text-gray-700 mb-2'>
Street
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
placeholder='Enter Street'
name={`addresses.${index}.street`}
{...register(`addresses.${index}.street`)}
/>
</div>
{/* City */}
{/* Zip Code */}
</div>
))}
Within this code excerpt, the enchantment of dynamically rendering address fields comes alive through the fields.map
function. Each iteration manifests a div element that hosts inputs for the street, city, and zip code. The index
parameter undertakes the vital role of ensuring that each field possesses a unique identity within the addresses
array.
Infusing Dynamism: Adding Addresses On-the-Fly
To bestow users with the ability to seamlessly add new addresses, let's enrich our form with the captivating "Add Address" button.
<button
className='bg-blue-500 px-6 py-2 rounded-md text-white hover:bg-blue-600 transition duration-300'
onClick={() => append({ street: '', city: '', zip: '' })}
type='button'
>
Add Address
</button>
Upon engaging with the "Add Address" button, the magic of the append
function materializes. This function introduces a fresh address object into the addresses
array, permitting users to effortlessly augment the form with additional address fields.
Unveiling the Full Example
Encompassing all the facets of our dynamic address form is the following comprehensive example:
import { useFieldArray, useForm } from 'react-hook-form';
const App = () => {
const { register, handleSubmit, control } = useForm({
defaultValues: {
firstName: '',
lastName: '',
email: '',
addresses: [
{
street: '',
city: '',
zip: '',
},
],
},
});
const { fields, append } = useFieldArray({
control,
name: 'addresses',
});
const onSubmit = (data) => {
console.log(data);
};
return (
<div className='flex items-center justify-center min-h-screen bg-gray-100'>
<form
className='w-[600px] p-8 bg-white rounded-lg shadow-lg'
onSubmit={handleSubmit(onSubmit)}
>
<h1 className='text-3xl text-center font-semibold text-gray-900 mb-6'>Address Form</h1>
<div className='mb-6 p-6 bg-gray-50 rounded-md shadow-md'>
<div className='flex flex-col mb-4'>
<label htmlFor='firstName' className='text-gray-700 mb-2'>
First Name
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
name='firstName'
placeholder='Enter First Name'
{...register('firstName')}
/>
</div>
<div className='flex flex-col mb-4'>
<label htmlFor='lastName' className='text-gray-700 mb-2'>
Last Name
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
name='lastName'
{...register('lastName')}
placeholder='Enter Last Name'
/>
</div>
<div className='flex flex-col mb-4'>
<label htmlFor='email' className='text-gray-700 mb-2'>
Email
</label>
<input
type='email'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
name='email'
placeholder='Enter Email'
{...register('email')}
/>
</div>
</div>
{fields.map((field, index) => (
<div className='mb-6 p-6 bg-gray-50 rounded-md shadow-md' key={field.id}>
<div className='flex flex-col mb-4'>
<label htmlFor={`addresses.${index}.street`} className='text-gray-700 mb-2'>
Street
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
placeholder='Enter Street'
name={`addresses.${index}.street`}
{...register(`addresses.${index}.street`)}
/>
</div>
<div className='flex flex-col mb-4'>
<label htmlFor={`addresses.${index}.city`} className='text-gray-700 mb-2'>
City
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
placeholder='Enter City'
name={`addresses.${index}.city`}
{...register(`addresses.${index}.city`)}
/>
</div>
<div className='flex flex-col'>
<label htmlFor={`addresses.${index}.zip`} className='text-gray-700 mb-2'>
Zip Code
</label>
<input
type='text'
className='border border-gray-300 rounded-md px-4 py-2 focus:outline-none focus:border-blue-500 transition duration-300'
placeholder='Enter Zip Code'
name={`addresses.${index}.zip`}
{...register(`addresses.${index}.zip`)}
/>
</div>
</div>
))}
<div className='flex items-center justify-end mt-6'>
<button
className='bg-blue-500 px-6 py-2 rounded-md text-white hover:bg-blue-600 transition duration-300'
onClick={() => append({ street: '', city: '', zip: '' })}
type='button'
>
Add Address
</button>
<button
className='bg-blue-500 ml-4 px-6 py-2 rounded-md text-white hover:bg-blue-600 transition duration-300'
type='submit'
>
Submit
</button>
</div>
</form>
</div>
);
};
export default App;
Key Insights
react-hook-form
delivers a streamlined approach to form management within React applications.The
useForm
anduseFieldArray
hooks constitute the foundation of form management and dynamic field handling.Dynamic fields seamlessly unfold through the use of the
fields
array.The
append
function introduces a new layer of dynamism by enabling users to effortlessly add new address fields.
Wrapping Up
In this comprehensive tutorial, we've embarked on a journey of crafting a dynamic address form utilizing the react-hook-form
library. We've covered setting up the form, crafting the user interface, deftly managing dynamic fields, and empowering users to enhance their experience by dynamically adding new addresses. By following this guide, you've gained a comprehensive understanding of creating interactive forms that flawlessly adapt to user interactions. With its user-friendly approach and performance optimization, react-hook-form
stands as a steadfast ally in your quest to develop seamless and user-centric forms.
Subscribe to my newsletter
Read articles from Yaseer Tasleem directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Yaseer Tasleem
Yaseer Tasleem
Front-End Developer