There are lots of ways to validate and form handling in React JS. You may write the custom validation rules for every input inside the form. It can be good when you have fewer inputs in the form. This can be handled by writing a few lines of code. But think, when you have a form with n number of inputs. Then is it sufficient to write the custom validation rules for every input for the required field, pattern check, etc? The answer is not at all. That’s why every framework and library has some additional library or package for validating the form. In React development, there are lots of npm packages are available for form handling. But, one of the most popular, easy, the customizable library is React Hook Form. Today, I will show you the use of React Hook Form library for React form validation.
This will make pretty easy the form validation in React js. I already shared a post on form handling using state hook with custom validation. But, in this post, I will show the form handling using React hook form.
Prerequisites
Before moving to this post, you must aware of the below terminology-
- Functional component in React
- useState hook
- HTML forms
By the end of this post, you will get the concept of handling form with validation in React js. So, let’s start with a new setup by creating an app.
Create App For Form Handling Using React Hook Form
To create a new app, open the terminal and hit the below command.
npx create-react-app registration-form
This will start creating the app and it will take a couple of minutes to set up the new app.
How to Use useEffect Hook in React Functional Component
After creating the app, let’s open it inside the VS Code editor and start the development server.
cd registration-form
npm start
This will redirect you to the browser with the below result.
In the next step, we will install Bootstrap for a basic registration form design.
Install Bootstrap in React
We have to create a very basic registration form. Hence, we will be using Bootstrap. Later, we will come to the other UI libraries.
Stay stick with the terminal and hit the below command to install the latest version of Bootstrap.
npm i bootstrap
We have Bootstrap installed in our app. Hence, we can start creating the form. But, before going to create the form, let’s install the React hook form library to handle the form stuff.
State in Functional Component in React Using useState Hook
Install React Hook Form Library
We will handle the entire form-related functionality like validation, data binding to the state, and the form submit. Hence, you will need to hit the below command in order to install this.
npm i react-hook-form
Create Components For React Hook Form
I will be creating a registration form without any API request handling. Therefore, it will require a single component having the form. So, come to the project folder, under the src folder, create a new folder named components. Now, inside the components folder, create a component with the name RegForm.jsx.
Here, we will create a basic Registration form with some inputs.
import React from "react";
export const RegForm = () => {
return (
<div className="container my-5">
<h5 className="text-center"> React Hook Form - Form Handling </h5>
<div className="row mt-4">
<div className="col-xl-6 col-lg-6 col-12 m-auto">
<form method="POST" autoComplete="off">
<div className="card shadow">
<div className="card-header">
<h5 className="card-title"> Register </h5>
</div>
<div className="card-body">
<div className="form-group">
<label htmlFor="name"> Name </label>
<input
type="text"
name="name"
className="form-control"
placeholder="Name"
/>
</div>
<div className="form-group my-3">
<label htmlFor="email"> Email </label>
<input
type="text"
name="email"
className="form-control"
placeholder="Email"
/>
</div>
<div className="form-group my-3">
<label htmlFor="password"> Password </label>
<input
type="password"
name="password"
className="form-control"
placeholder="Password"
/>
</div>
<div className="form-group my-3">
<label htmlFor="address"> Address </label>
<textarea
name="address"
className="form-control"
placeholder="Address"
></textarea>
</div>
<div className="form-group">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
Now, for rendering this RegForm component, you have to call this component inside the App component. Here, App component will look like this.
import React from "react";
import { RegForm } from "./components/RegForm";
export const App = () => {
return <RegForm />;
};
We are using bootstrap for the form design. Therefore, this will need to import inside the index.js file.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import { App } from "./App";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.min.js";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
This will generate the below result with a basic form. You may add more fields as per your requirement.
Currently, the above form has no action and no functionality. So, it’s time to use the React hook form for handling this form.
How to Create Loading Spinner Using Bootstrap in React JS
Use React Hook Form in React Js
Basically, this React Hook form is a hook. It is similar to other hooks in React. So, in the very first step, you will need to import it inside the component at the top.
import { useForm } from "react-hook-form";
Next, before the return of the component, you will need to invoke as shown below.
const { register, handleSubmit, formState: { errors } } = useForm();
This is the syntax of using the React Hook form. Let me explain the above line.
- register– The main key concept of the register is to register the form input component into the hook. By registering the component, the value of that form component will be available for form submission as well as validation.
- handleSubmit– After the component registered to the hook, you can access the form data on the form submit. Here, you will need to pass this handleSubmit inside the form submit event.
- errors– Mainly, this will hold the validation errors. The react hook form supports different type of validation like required, min, max, minLength, maxLength, pattern, etc. We will see these validation type one by one.
Let’s try to implement it within the registration form.
API Handling in React Functional Component Using Hook
Apply React Hook Form in Registration Form
For applying React Hook form, you need to import the hook. After that register all inputs with their actual name that you defined in the name attribute. Lastly, you will need to create the formSubmit() event. On formSubmit(), you will get the form inputs data.
Take a look at the below code.
import React from "react";
import { useForm } from "react-hook-form";
export const RegForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const formSubmit = (data) => {
console.log("data", data);
};
return (
<div className="container my-5">
<h5 className="text-center"> React Hook Form - Form Handling </h5>
<div className="row mt-4">
<div className="col-xl-6 col-lg-6 col-12 m-auto">
<form
method="POST"
onSubmit={handleSubmit(formSubmit)}
autoComplete="off"
>
<div className="card shadow">
<div className="card-header">
<h5 className="card-title"> Register </h5>
</div>
<div className="card-body">
<div className="form-group">
<label htmlFor="name"> Name </label>
<input
type="text"
name="name"
className="form-control"
placeholder="Name"
{...register("name")}
/>
</div>
<div className="form-group my-3">
<label htmlFor="email"> Email </label>
<input
type="text"
name="email"
className="form-control"
placeholder="Email"
{...register("email")}
/>
</div>
<div className="form-group my-3">
<label htmlFor="password"> Password </label>
<input
type="password"
name="password"
className="form-control"
placeholder="Password"
{...register("password")}
/>
</div>
<div className="form-group my-3">
<label htmlFor="address"> Address </label>
<textarea
name="address"
className="form-control"
placeholder="Address"
{...register("address")}
></textarea>
</div>
<div className="form-group">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
In the above snippet, I did the same as I mentioned above. Let me explain again.
- After importing the hook, I invoked it with the event named register, handleSubmit, and errors.
- In the next step, I have created the formSubmit event in the form element. Inside this formSubmit event, I passed the handleSubmit. So, that it will capture the form data on submit.
- Lastly, I have registered the inputs like name, email, password, and address with the name field.
To check the console log, let’s refresh the page and open the developer console window. Fill up the details and submit the form. In the result, you will see the form data has been captured automatically without writing any onChange event.
File Upload in React JS Using Laravel 8 RESTful API
Apply Form Validation Using React Hook Form
React hook form provides the client-side validation rules as follows-
- required
- min
- max
- minLength
- maxLength
- pattern
- validate
You can apply these all validation rules inside the inputs. Let’s see in the below code. I have set the required validation rule.
import React from "react";
import { useForm } from "react-hook-form";
export const RegForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const formSubmit = (data) => {
console.log("data", data);
};
console.log("errors", errors);
return (
<div className="container my-5">
<h5 className="text-center"> React Hook Form - Form Handling </h5>
<div className="row mt-4">
<div className="col-xl-6 col-lg-6 col-12 m-auto">
<form
method="POST"
onSubmit={handleSubmit(formSubmit)}
autoComplete="off"
>
<div className="card shadow">
<div className="card-header">
<h5 className="card-title"> Register </h5>
</div>
<div className="card-body">
<div className="form-group">
<label htmlFor="name"> Name </label>
<input
type="text"
name="name"
className="form-control"
placeholder="Name"
{...register("name", {
required: true,
})}
/>
</div>
<div className="form-group my-3">
<label htmlFor="email"> Email </label>
<input
type="text"
name="email"
className="form-control"
placeholder="Email"
{...register("email", {
required: true,
})}
/>
</div>
<div className="form-group my-3">
<label htmlFor="password"> Password </label>
<input
type="password"
name="password"
className="form-control"
placeholder="Password"
{...register("password", {
required: true,
})}
/>
</div>
<div className="form-group my-3">
<label htmlFor="address"> Address </label>
<textarea
name="address"
className="form-control"
placeholder="Address"
{...register("address", {
required: true,
})}
></textarea>
</div>
<div className="form-group">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
I have displayed the validation errors object in the console. Let’s see the below result.
Here, in this result, the validation error message is displayed in the console. But, we have to show it in the form.
How to Use Axios in React JS For API Requests Handling
Display Validation Error Message Using React Form
Let’s map these validation errors object to display the error message right to the input. Hence, in order to do that you have to check the input has an error then show it in the form.
import React from "react";
import { useForm } from "react-hook-form";
export const RegForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const formSubmit = (data) => {
console.log("data", data);
};
console.log("errors", errors);
return (
<div className="container my-5">
<h5 className="text-center"> React Hook Form - Form Handling </h5>
<div className="row mt-4">
<div className="col-xl-6 col-lg-6 col-12 m-auto">
<form
method="POST"
onSubmit={handleSubmit(formSubmit)}
autoComplete="off"
>
<div className="card shadow">
<div className="card-header">
<h5 className="card-title"> Register </h5>
</div>
<div className="card-body">
<div className="form-group">
<label htmlFor="name"> Name </label>
<input
type="text"
name="name"
className="form-control"
placeholder="Name"
{...register("name", {
required: true,
})}
/>
<span>{errors.name ? 'Name is required' : ''} </span>
</div>
<div className="form-group my-3">
<label htmlFor="email"> Email </label>
<input
type="text"
name="email"
className="form-control"
placeholder="Email"
{...register("email", {
required: true,
})}
/>
<span>{errors.email ? 'Email is required' : ''} </span>
</div>
<div className="form-group my-3">
<label htmlFor="password"> Password </label>
<input
type="password"
name="password"
className="form-control"
placeholder="Password"
{...register("password", {
required: true,
})}
/>
<span>{errors.password ? 'Password is required' : ''} </span>
</div>
<div className="form-group my-3">
<label htmlFor="address"> Address </label>
<textarea
name="address"
className="form-control"
placeholder="Address"
{...register("address", {
required: true,
})}
></textarea>
<span>{errors.address ? 'Address is required' : ''} </span>
</div>
<div className="form-group">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
In the above code, I have checked the error object and set the error message for the required rule.
But this way you cannot set multiple error messages for the different validation rules. So, let’s simplify it by adding more validation errors with messages.
Form Handling in React JS With Validation Using React State
Set Multiple Validation Rules in React Hook Form
For the required field, we will change the boolean value by passing the required validation message directly into it. Also, we will set minLength, maxLength, pattern, etc. But, for displaying the validation error message, we won’t check the type of error. We will display the message from every input error object.
Hence, it will need to set the custom message into the message object of the errors. So, let’s follow the below code.
import React from "react";
import { useForm } from "react-hook-form";
export const RegForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const formSubmit = (data) => {
console.log("data", data);
};
return (
<div className="container my-5">
<h5 className="text-center"> React Hook Form - Form Handling </h5>
<div className="row mt-4">
<div className="col-xl-6 col-lg-6 col-12 m-auto">
<form
method="POST"
onSubmit={handleSubmit(formSubmit)}
autoComplete="off"
>
<div className="card shadow">
<div className="card-header">
<h5 className="card-title"> Register </h5>
</div>
<div className="card-body">
<div className="form-group">
<label htmlFor="name"> Name </label>
<input
type="text"
name="name"
className={`form-control ${
errors.name ? "is-invalid" : ""
}`}
placeholder="Name"
{...register("name", {
required: "Name is required",
pattern: {
value: /^[a-zA-Z]+$/,
message: "Name must be a valid string",
},
minLength: {
value: 3,
message: "Name should be greater than 3 characters",
},
maxLength: {
value: 20,
message: "Name shouldn't be greater than 20 characters",
},
})}
/>
<div className="invalid-feedback">
{errors?.name?.message}
</div>
</div>
<div className="form-group my-3">
<label htmlFor="email"> Email </label>
<input
type="text"
name="email"
className={`form-control ${
errors.email ? "is-invalid" : ""
}`}
placeholder="Email"
{...register("email", {
required: "Email is required",
pattern: {
value: /^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$/,
message: "Email must be a valid email address",
},
})}
/>
<div className="invalid-feedback">
{errors?.email?.message}
</div>
</div>
<div className="form-group my-3">
<label htmlFor="password"> Password </label>
<input
type="password"
name="password"
className={`form-control ${
errors.password ? "is-invalid" : ""
} `}
placeholder="Password"
{...register("password", {
required: "Password is required",
pattern: {
value: /^[a-zA-Z]+[0-9]+$/,
message: "Password must be alpha numeric",
},
minLength: {
value: 5,
message: "Password must be atleast 5 characters",
},
})}
/>
<div className="invalid-feedback">
{errors?.password?.message}
</div>
</div>
<div className="form-group my-3">
<label htmlFor="address"> Address </label>
<textarea
name="address"
className={`form-control ${
errors.address ? "is-invalid" : ""
}`}
placeholder="Address"
{...register("address", {
required: "Address is required",
minLength: {
value: 4,
message: "Address is too short",
},
maxLength: {
value: 40,
message: "Address is too long",
},
})}
></textarea>
<span className="text-danger">
{errors?.address?.message}
</span>
</div>
<div className="form-group">
<button type="submit" className="btn btn-success"> Save </button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
In the above form, I have set the validation error message and displayed the same message right to the input.
Check validation error messages for minLength, maxLength, and pattern rule.
As the result, you may see the applied validations are working properly. You can write more advanced pattern checks using regular expressions. The hook form supports these validations.
Final Words
React hook form library is really impressive in terms of form handling. The registered inputs value is available for the form submission as well as validation. After invoking the form hook, you can use it’s object for registering input and form submit event. I hope this will make sense for you all. You may enhance this to more complex form handling as per your requirements. This was a basic demonstration to give you an idea of how to use the hook form library in React.
Leave a Reply