Validating user input on forms prior to submission, in my opinion, is one of the most important and fundamental things about a website these days.
Thank god we have several options to validate them, in the React ecosystem there are lots of libraries. However many of these libraries either end up having a huge boilerplate, which is sometimes scary, even when implementing in a form with few fields. Or they decrease application performance.
Keeping these points in mind, I always end up looking for a solution that is simple, with little boilerplate and that has a great performance.
Apart from that, another thing I'm looking for is a form validation library that lets you use a library to validate schemas, such as Joi, Yup, etc. This way I can reuse the schema code in the frontend and backend.
It's exactly for all these reasons that I love working with React Hook Form.
Let's code
First we will add the following dependencies to our React application:
npm install react-hook-form @hookform/resolvers yup
Now let's pretend this is your form:
import React from "react";
const App = () => {
return (
<form>
<h2>Lets sign you in.</h2>
<br />
<input placeholder="email" type="email" required />
<br />
<input
placeholder="password"
type="password"
required
/>
<br />
<button type="submit">Sign in</button>
</form>
);
};
export default App;
Now let's import React Hook Form
into our project:
import React from "react";
import { useForm } from "react-hook-form";
// Hidden for simplicity
Then let's get the following things from the useForm()
hook:
const App = () => {
const { register, handleSubmit, formState: { errors }, reset } = useForm();
return (
// Hidden for simplicity
};
Quick overview
- The
register()
method allows registering an element and applying the appropriate validation rules. - The
handleSubmit()
function will receive the form data if validation is successful. - The
reset()
function will clear all form fields or reset to initial values. - In this case, we are using
formState
to return form errors in an easier way.
Now we have to import Yup into our project and then let's create our schema.
// Hidden for simplicity
import * as yup from "yup";
const schema = yup.object().shape({
email: yup.string().email().required(),
password: yup.string().min(8).max(32).required(),
});
Now we have to import @hookform/resolvers
so we can use our Yup schema to validate input values. Like this:
import { yupResolver } from "@hookform/resolvers/yup";
// Hidden for simplicity
const App = () => {
const { register, handleSubmit, formState: { errors }, reset } = useForm({
resolver: yupResolver(schema),
});
return (
// Hidden for simplicity
};
Now we have to create our function to submit the data (which in this example will be a simple log). Just like we're going to add the reset()
method inside our function so that form inputs are cleared as soon as they're submitted.
Lastly let's add the handleSubmit()
method to our form. Similar to this:
const App = () => {
const { register, handleSubmit, formState: { errors }, reset } = useForm({
resolver: yupResolver(schema),
});
const onSubmitHandler = (data) => {
console.log({ data });
reset();
};
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
// Hidden for simplicity
</form>
};
The next step is to register our inputs, assigning their names according to the properties of our schema:
const App = () => {
// Hidden for simplicity
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<h2>Lets sign you in.</h2>
<br />
<input {...register("email")} placeholder="email" type="email" required />
<br />
<input
{...register("password")}
placeholder="password"
type="password"
required
/>
<br />
<button type="submit">Sign in</button>
</form>
);
};
Last but not least, let's add the error messages for each of the inputs:
const App = () => {
// Hidden for simplicity
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<h2>Lets sign you in.</h2>
<br />
<input {...register("email")} placeholder="email" type="email" required />
<p>{errors.email?.message}</p>
<br />
<input
{...register("password")}
placeholder="password"
type="password"
required
/>
<p>{errors.password?.message}</p>
<br />
<button type="submit">Sign in</button>
</form>
);
};
Now with everything finished, the code should look like this:
import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
const schema = yup.object().shape({
email: yup.string().email().required(),
password: yup.string().min(8).max(32).required(),
});
const App = () => {
const { register, handleSubmit, formState: { errors }, reset } = useForm({
resolver: yupResolver(schema),
});
const onSubmitHandler = (data) => {
console.log({ data });
reset();
};
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<h2>Lets sign you in.</h2>
<br />
<input {...register("email")} placeholder="email" type="email" required />
<p>{errors.email?.message}</p>
<br />
<input
{...register("password")}
placeholder="password"
type="password"
required
/>
<p>{errors.password?.message}</p>
<br />
<button type="submit">Sign in</button>
</form>
);
};
export default App;
In order for you to have an idea of the final result, you should have something similar to what you see in the gif:
What about you
What library do you use to validate your forms in React?
Top comments (24)
Hi! Where did you got that look of form? Some css, which didn't show or it is some inbuilt in hook Forms? How I can use my look then?
I used water.css
what is that
it work, thank you so much
very usefull, i love yup and this comination with useForms is amazing. Thank you. Do you have another one for Redux/Toolkit
so usefull thank u very much!!!
Amazing! Thank you for sharing.
hii, i am using react-hook-form with Typescript
the problem is with typescript it is asking me to add Type for resolver
Great explanation. My first search got successfully at dev.to
Thanks for the feedback! I am very happy to hear that the article helped you!
Thank you for this tutorial, greate job ;)
Thank you very much for the feedback! 🤗
Amazing explanation! Thank you so much, you helped me understand this quickly
Thank you very much for the feedback! 💪
That was really useful , I got it in less than a minute .greate job
Glad to know and thanks so much for your feedback! 👊