Table of contents
No headings in the article.
Introduction:
Managing forms in web applications can be a complex task, especially when dealing with validation rules, error handling, and form submissions. The React useForm
plugin library offers a powerful and elegant solution to simplify form management in React applications. In this tutorial, we will walk through a comprehensive example of using the useForm
library to handle form lifecycle events, such as validations, rules, and form submissions. By the end of this tutorial, you will have a solid understanding of how to use the React useForm
plugin library to efficiently manage forms in your React applications.
Prerequisites:
Basic understanding of JavaScript and React
Familiarity with React functional components and hooks
Knowledge of form validation and handling in web applications
Getting Started:
To begin, let's install the React useForm
plugin library by running the following command:
npm install react-hook-form
Now that we have the library installed, let's dive into a practical example of using the useForm
library to manage a form lifecycle.
Example: Create and Update Client Action Items
In this example, we will create a form to create and update client action items. The form will include fields for title
, category
, description
, and target_date
. We will use the useForm
library to manage form state, handle validations, and submit the form data to an API.
Full Code Example;
import { useForm } from 'react-hook-form';
export default function CreateClientActionItem({item}) {
const {
register,
handleSubmit,
formState: {
errors
}
} = useForm({
defaultValues: {
title: item?.title ?? '',
category: item?.category ?? '',
description: item?.description ?? '',
target_date: item?.target_date ?? '',
}
});
const onSubmit = (data) => {
let url = '/test/store-url';
axios.post(url, data).then((res) => {
if (res.data.status === 'success') {
alert("Success");
} else {
alert("Error");
}
}).catch((err) => {
notifyError("Unknown error occurred while creating action item")
});
}
const onUpdate = (data) => {
let url = '/test/update-url';
axios.put(url, data).then((res) => {
if (res.data.status === 'success') {
alert("Success");
} else {
alert("Error");
}
}).catch((err) => {
notifyError("Unknown error occurred while updating action item")
});
}
const onError = (data) => {
console.log(data);
}
return <form onSubmit={handleSubmit((item == null) ? onSubmit : onUpdate, onError)}>
<div
className="flex flex-col gap-[24px] rounded-[5px] w-full">
<div className="flex flex-col gap-[16px]">
<div className="flex flex-col gap-[16px]">
<label htmlFor="title">Title</label>
<input type="text" {...register('title', {
required: "Title is required",
minLength: {
value: 2,
message: "Title must be at least 2 characters"
},
maxLength: {
value: 50,
message: 'Title can be maximum 50 characters'
}
})} name="title" id="title"
className="w-full p-[10px] border border-gray-500 rounded-[5px] pl-10 pr-12 f-16-400-g-sans"
placeholder="Title"/>
{errors.title ?
<p className="text-red-500">{errors.title.message}</p> : null}
</div>
<div className="flex flex-col gap-[16px]">
<label htmlFor="category">Category (optional)</label>
<input type="text" {...register('category', {
minLength: {
value: 2,
message: "Category must be at least 2 characters"
},
maxLength: {
value: 50,
message: 'Category can be maximum 50 characters'
}
})} name="category" id="category"
className="w-full p-[10px] border border-gray-500 rounded-[5px] pl-10 pr-12 f-16-400-g-sans"
placeholder="Category"/>
{errors.category ?
<p className="text-red-500">{errors.category.message}</p> : null}
</div>
<div className="flex flex-col gap-[16px]">
<label htmlFor="description">Description</label>
<textarea {...register('description', {
required: "Description is required",
minLength: {
value: 2,
message: "Description must be at least 2 characters"
},
})} name="description" id="description"
className="w-full p-[10px] border border-gray-500 rounded-[5px] pl-10 pr-12 f-16-400-g-sans"
placeholder="Description"/>
{errors.description ?
<p className="text-red-500">{errors.description.message}</p> : null}
</div>
<div className="flex flex-col gap-[16px]">
<label htmlFor="target_date">Target date (optional)</label>
<input type="date" {...register('target_date')} name="target_date"
id="target_date"
className="w-full p-[10px] border border-gray-500 rounded-[5px] pl-10 pr-12 f-16-400-g-sans"
placeholder="Description"/>
</div>
</div>
<div className="flex flex-row items-center gap-[40px]">
<button type="submit" className="primary-button bg-defaultPrimary">{!item ? 'Create action item' : 'Update action item'}</button>
<h1 onClick={closeHandler} className="text-defaultPrimary cursor-pointer">Cancel</h1>
</div>
</div>
</form>
}
Code Explanation:
1. Import useForm
:
Start by importing the useForm
hook from the library:
import { useForm } from 'react-hook-form';
2. Initialize useForm
:
In the CreateClientActionItem
functional component, initialize the useForm
hook and destructure its returned properties:
const {
register,
handleSubmit,
formState: {
errors
}
} = useForm({
defaultValues: {
title: item?.title ?? '',
category: item?.category ?? '',
description: item?.description ?? '',
target_date: item?.target_date ?? '',
}
});
The defaultValues
option allows you to set initial values for the form fields.
In this example, we use the optional chaining operator “?”
and the nullish coalescing operator “??”
to set the default values to empty strings if item
is not provided.
3. Register form fields:
To register form fields with the useForm
hook, use the register
function provided by the hook. The register
function takes two arguments: the field name and an optional configuration object. The configuration object can include validation rules, such as required
, minLength
, and maxLength
. If a validation rule fails, an error message is provided and stored in the errors
object.
For example, registering the title
field with validation rules:
<input type="text" {...register('title', {
required: "Title is required",
minLength: {
value: 2,
message: "Title must be at least 2 characters"
},
maxLength: {
value: 50,
message: 'Title can be maximum 50 characters'
}
})} ... />
Similarly, register the category
, description
, and target_date
fields with appropriate validation rules.
4. Handle form submission:
The handleSubmit
function is used to manage form submissions. It takes two arguments: a function to be executed on a successful submission and a function to be executed if there are any errors.
In our example, we use the onSubmit
function for creating a new action item and the onUpdate
function for updating an existing one:
<form onSubmit={handleSubmit((item == null) ? onSubmit : onUpdate, onError)}>
The ternary operator checks if item
is null
, which indicates a new action item should be created. If item
is not null
, it means we are updating an existing action item.
- Display error messages:
If there are any validation errors, they are stored in the errors
object. To display error messages, check if an error exists for a specific form field and render the error message accordingly:
{errors.title ?
<p className="text-red-500">{errors.title.message}</p> : null}
In this example, if there is an error for the title
field, the error message is displayed in a paragraph element with a text-red-500
class. Similarly, error messages are displayed for other fields such as category
and description
.
- Form submission logic:
In the onSubmit
and onUpdate
functions, we use the axios
library to send HTTP requests to the API for creating or updating an action item.
The response is checked for the status
property to determine if the request was successful.
If successful, we display a success notification, update the item, and close the form. If unsuccessful, we display an error notification:
axios.post(url, data).then((res) => {
if (res.data.status === 'success') {
alert('success');
} else {
alert('error');
}
}).catch((err) => {
notifyError("Unknown error occurred while creating action item")
});
In the onError
function, we log the error data to the console. In a real-world scenario, you might want to handle the errors differently, such as by displaying a user-friendly error message.
Conclusion:
In this tutorial, we have explored how to use the React useForm
plugin library to handle form lifecycle events, including validations, rules, and form submissions.
By using this powerful library, you can streamline form management in your React applications and build robust, user-friendly forms with ease.
The provided code example demonstrates a practical use case that can be adapted to suit your specific requirements. With this knowledge, you can now confidently tackle form management challenges in your React projects.
Happy coding!