React Hook Form with Zod
In this article we'll build a basic form using React Hook Form with zod validation.
We'll focus on the basics of React Hook Form. This guide won't cover styling or more advanced use cases such as working with external UI libraries and using "Controller".
Why React Hook Form?
React Hook Form is an amazing lightweight tool. It allows to handle form state and validate it very easily. It is also more performant than normal controlled forms. It doesn't re-render the component on every input change, unlike the useState approach. Try to put some data in this form and look at the re-renders counter.
See? That's a lot of unnecessary re-renders. That's because this form uses useState
. Now try the same with this form which uses React Hook Form
That's much better.
With all of that, it is very easy to understand. Let's build a form like this.
Installing dependencies
We need to install these three dependencies to begin.
npm i react-hook-form zod @hookform/resolvers
Creating a schema
First, let's declare the form schema. It's a good idea to start with this because it makes creating the form easier.
Zod validation is very easy to understand. It allows you to check if user provided correct email address or to check if the username or password is between 4 and 16 and provide specific message if not. I strongly encourage you to take a look at zod documentation. for more specific use cases.
To use it with React Hook Form we need to make a type from this schema.
Now TFormSchema
is the type of our form.
Starting with React Hook Form
Let's start creating our form. At first we'll take a look at useForm
hook. It provides for us many properties and functions. For now let's focus on two of them.
You probably already know what they do:
register
is used to "register" the input in our FormDatahandleSubmit
is the function we want to pass as a onSubmit event on our form.
To connect our zod validation to this form we need to use schema type as a generic.
useForm
takes an object as its first argument, and in this case, we need to specify which resolver we want to use. zodResolver
function which takes previously created schema as a argument comes from @hookform/resolvers/zod
Creating a form.
We're ready to create our form. Let's start with just a skeleton.
Caution
If you are using Next.js don't forget to put "use client"
at the top of your file.
But how to use register
and handleSubmit
?
register
is a function that take the name of our input as its first argument. The name must match the schema, but don't worry — it's type-safe, and TypeScript will assist you. It return all necessary properties which we want on our input. It should look like this:
handleSubmit
takes a function as a first argument which we want to execute at form submission. It will pass all input values as a first argument to it.
SubmitHandler
type is from React Hook Form as well.
Errors
Our form works as expected but we're not doing anything with errors. To handle it we'll use a formState
object from useForm
hook. It has errors
object which contains errors for every registered input.
Now we can check if an error occurred for a specific input and display it conditionally.
You may also want to reset inputs values after submission. To do it just use reset
function provided by useForm
hook at the end of the submitForm
.
That's all! We built out first form together using React Hook Form. It provides many more things than that. For more specific use cases and more information check out docs here.
Our finished form look like this:
We achieved it with this code:
Don't forget to style it in a user-friendly way. I used styling from shadcn/ui but it is not provided in code snippets. For more take a closer look at React Hook Form documentation.
Thanks for reading!