Validating inputs from forms is very important to keep a clean and organized backend service. If you have to write a program that validates and handles form input based on different cases, this can be a difficult task. But with React Hook Form, we worry less about how to handle errors from web forms.
React Hook Form is a library that enables us to accept only valid data from the user. With React Hook Form, we can create performant React forms, which validate form inputs and make sure they are in the exact format required by the server.
In this tutorial, I will guide you through the process of validating data from your React forms using React Hook Form.
Setup a React project
- Open your terminal and run the command below to create a React app project
npx create-react-app reacthookform
- Install React Hook Form. After installing React Hook Form, skip to the next section if you're not using Tailwind CSS.
npm install react-hook-form
- Optional: Install Tailwind CSS by running the command below. Tailwind CSS is utility-first CSS framework for building mordern user interfaces.
npm install -D tailwindcss postcss autoprefixer
- Generate tailwind.config.js and postcss.config.js configuration files by running:
npx tailwindcss init -p
- Open
tailwind.config.js
and copy the code below:
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
theme: {
extend: {},
},
plugins: [],
};
- In the
./src/index.css
file, add Tailwind directive to your CSS:
@tailwind base;
@tailwind components;
@tailwind utilities;
Data Fetching in Next.js v12.1 Simplified (with use cases)
David Asaolu ・ Mar 9 '22
React Hook Form Validation
I will explain this concept by creating a user registration form that accepts different information from the user, such as first name, last name, age, gender, email address, and password.
A popular way to handle these inputs in React is to keep all the data in a state, but React Hook Form provides a more efficient way of handling the form data.
Let's examine the code below:
import { useForm } from 'react-hook-form';
export default function Home() {
const { register, handleSubmit } = useForm();
const submitForm = (data) => {
console.log(data);
};
return (
<div>
<main className="flex items-center justify-center py-8 min-h-screen">
<form
onSubmit={handleSubmit(submitForm)}
className="flex flex-col w-[500px] gap-4"
>
<label htmlFor="firstName">First Name</label>
<input
type="text"
className="border-2 py-2 px-4"
{...register('firstName')}
/>
<label htmlFor="lastName">Last Name</label>
<input
type="text"
className="border-2 py-2 px-4"
{...register('lastName')}
/>
<label htmlFor="age">Age</label>
<input
type="number"
className="border-2 py-2 px-4"
{...register('age')}
/>
<select {...register('gender')} className="border-2 py-2 px-4">
<option value="female">Female</option>
<option value="male">Male</option>
<option value="others">Others</option>
</select>
<label htmlFor="email">Email Address</label>
<input
type="email"
className="border-2 py-2 px-4"
{...register('email')}
/>
<label htmlFor="password">Password</label>
<input
type="password"
className="border-2 py-2 px-4"
{...register('password')}
/>
<button
className="py-2 px-4 border bg-slate-300 hover:bg-slate-500 hover:text-slate-50"
type="submit"
>
Submit
</button>
</form>
</main>
</div>
);
}
The code snippet above introduces a hook called useForm, which contains the functions
register
andhandleSubmit
.
- useForm() is a custom hook in React Form Hook used for managing forms with ease. You can find some optional arguments here
- register("variable_name") is a function that accepts the name of the input field as an argument. This argument represents the property name of the input field.
- handleSubmit() is function that wraps the submit function. It handles validation of the data provided by the user before sending it to the server.
How then can we validate the user input?
The register()
function is used to validate form inputs. It accepts two arguments - the property name of the input field and the validation rules. A validation rule is an object containing the set of rules to be met by each input field, as well as the error messages to display when the rules are not met.
Let's take a look at an example
I will be using the user registration form we created earlier to explain this concept.
import { useForm } from 'react-hook-form';
export default function Home() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const submitForm = (data) => {
console.log(data);
};
return (
<div>
<main className="flex items-center justify-center py-8 min-h-screen">
<form
onSubmit={handleSubmit(submitForm)}
className="flex flex-col w-[500px] gap-4"
>
<label htmlFor="firstName">First Name</label>
<input
type="text"
className="border-2 py-2 px-4"
{...register('firstName', {
required: 'Please enter your first name',
})}
/>
{/* --- displays error message for first name */}
{errors?.firstName && (
<p className="text-red-500">{errors.firstName.message}</p>
)}
<label htmlFor="lastName">Last Name</label>
<input
type="text"
className="border-2 py-2 px-4"
{...register('lastName', {
required: 'Please enter your last name',
})}
/>
{/* --- displays error message for last name */}
{errors?.lastName && (
<p className="text-red-500">{errors.lastName.message}</p>
)}
<label htmlFor="age">Age</label>
<input
type="number"
className="border-2 py-2 px-4"
{...register('age', {
required: 'Please enter your age',
valueAsNumber: true,
min: {
value: 16,
message: 'You must be greater than 15',
},
})}
/>
{/* --- displays error message for age */}
{errors?.age && <p className="text-red-500">{errors.age.message}</p>}
<select
{...register('gender', { required: 'Please provide your gender' })}
className="border-2 py-2 px-4"
>
<option value="female">Female</option>
<option value="male">Male</option>
<option value="others">Others</option>
</select>
{/* --- displays error message for gender */}
{errors?.gender && (
<p className="text-red-500">{errors.gender.message}</p>
)}
<label htmlFor="email">Email Address</label>
<input
type="email"
className="border-2 py-2 px-4"
{...register('email', { required: 'Please enter a valid enail' })}
/>
{/* ---displays error message for email */}
{errors?.email && (
<p className="text-red-500">{errors.email.message}</p>
)}
<label htmlFor="password">Password</label>
<input
type="password"
className="border-2 py-2 px-4"
{...register('password', {
required: 'Please enter your password',
minLength: {
value: 8,
message: 'Your password must contain at least 8 characters',
},
})}
/>
{/* ---displays error message for password */}
{errors?.password && (
<p className="text-red-500">{errors.password.message}</p>
)}
<button
className="py-2 px-4 border bg-slate-300 hover:bg-slate-500 hover:text-slate-50"
type="submit"
>
Submit
</button>
</form>
</main>
</div>
);
}
From the code snippet above,
- I imported
formState: { errors }
- an object containing the validation rules and error messages for each of the registered form input fromuseForm()
. - The validation rule in the
register()
function has the property ofrequired
- meaning the form fields are important, and if they are left empty, it displays the error message - which is the value of therequired
property. - In age, the
register()
function has therequired
property -valueAsNumber
andmin
.valueAsNumber
converts the user's input to a data type of Number.min
is an object containing two keys -value
andmessage
.value
contains the minimum value the form accepts andmessage
is a custom error message you will like to show the user. - For the password, the
register()
function has the key -minLength
which is an object with two keys,value
andmessage
.value
refers to the number of characters andmessage
is the error message to displayed if the number of characters is not upto the required value.
Conclusion
According to https://react-hook-form.com, React Hook Form reduces the amount of code you need to write while removing unnecessary re-renders, so you don't have to worry about performance issues. React Hook Form optimizes the performance of your React forms. With lesser code, you can build faster and more optimized web forms.
Thank you for reading!
Writer's Corner
Hi, I am open to freelance technical writing gigs and remote opportunities. Let's work together. 📧: asaoludavid234@gmail.com
Top comments (0)