# Handling Forms in React Using React Hook Form  ZOD and TypeScript

One major part of dealing with forms as a developer is validating the different inputs you have. When [dealing with simple forms](https://blog.thereactivedeveloper.com/form-handling-in-reactjs), things are generally manageable. But as your form gets more complex with more inputs and you need to add various validations, it becomes a complicated task.

Instead of writing all the logic and validation rules in your forms manually, we can make use of libraries such as `react-hook-form` or `formik`. In this post, we are going to look at handling and validating forms in a React application using `react-hook-form`

## What is React Hook Form

React Hook Form is a library that helps you validate forms in React. It is a minimal library without any other dependencies while being performant and straightforward to use, requiring developers to write fewer lines of code than other form libraries.

It takes a slightly different approach than other form libraries in the React ecosystem by adopting the use of uncontrolled inputs using `ref` instead of depending on the state to control the inputs. This approach makes the forms more performant and reduces the number of re-renders.

To install React Hook Form, run the following command:

```bash
npm install react-hook-form
```

Check my previous blog [here](https://blog.thereactivedeveloper.com/form-handling-in-reactjs) to read more on handling forms in React without using a library

## What is ZOD

Zod is a JavaScript validation library that allows you to define schemas that model the shape and constraints of your data. These schemas generate type safety, automatic validation, and useful error messages. Some key aspects of Zod include:

* Validation of data types, strings, numbers, objects etc.
    
* Customizable error messages
    
* Support for nested objects and arrays
    
* Code auto-completion when using a Zod schema
    
* Type safety with TypeScript integration
    

By modeling application data with Zod schemas, you get built-in validation with helpful errors. It makes it easy to reuse validation logic across your application.

To work with Zod in React, you need to install the library and a resolver

```bash
npm install @hookform/resolvers zod
```

## Setting Up Our Form

1. Import the required components and hooks:
    

```typescript
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
```

2. Define your form schema using Zod:
    
    Zod allows us to define a schema that lays out the exact shape and constraints we want to apply to our form data. Let's create one for our form:
    
    ```typescript
    export const createUserSchema = z.object({
      name: z.string().min(2, { message: 'Name is required' }),
      email: z.string().email('Must be a valid email'),
      age: z.number().positive().int(),
    });
    ```
    
    This schema defines the fields we expect along with constraints like minimum length, email validation, etc. Zod will automatically generate useful error messages for us when validation fails.
    
3. Create form component:
    
    Using the schema we created above, we can create form with corresponding inputs as illustrated below.
    
    ```typescript
    type FormData = z.infer<typeof createUserSchema>;
    
    function UserForm() {
      const {
        register,
        handleSubmit,
        formState: { errors },
      } = useForm<FormData>({
        resolver: zodResolver(createUserSchema),
      });
    
      const onSubmit = (data: FormData) => {
        console.log(data);
        // Handle form submission
      };
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <div>
            <label htmlFor="name">Name</label>
            <input id="name" {...register('name')} />
            {errors.name && <span>{errors.name.message}</span>}
          </div>
    
          <div>
            <label htmlFor="email">Email</label>
            <input id="email" {...register('email')} />
            {errors.email && <span>{errors.email.message}</span>}
          </div>
    
          <div>
            <label htmlFor="age">Age</label>
            <input id="age" type="number" {...register('age', { valueAsNumber: true })} />
            {errors.age && <span>{errors.age.message}</span>}
          </div>
    
          <button type="submit">Submit</button>
        </form>
      );
    }
    ```
    
    Here is what's happening:
    
    * We use `z.infer<typeof createUserSchema>` to infer the TypeScript type from our Zod schema.
        
    * The `useForm` hook is initialized with the zodResolver, which connects React Hook Form with our Zod schema.
        
    * We destructure `register`, `handleSubmit`, and `errors` from the `useForm` hook.
        
    * The `register` function is used to register our inputs with React Hook Form.
        
    * We display error messages conditionally based on the `errors` object.
        
    * We use the `handleSubmit` method connect to our own `onSubmit` method to handle form submission. The `onSubmit` method will be called when all validation passes and will receive the form data which you can handle as needed such as submitting it to an api.
        
4. Advanced Usage:
    
    React Hook Form and Zod offer more advanced features that you can explore:
    
    * Custom error messages
        
    * Conditional fields
        
    * Array fields
        
    * Async validation
        
    
    Here's an example of a more complex schema with custom error messages:
    
    ```typescript
    const advancedSchema = z.object({
      username: z.string()
        .min(3, { message: 'Username must be at least 3 characters long' })
        .max(20, { message: 'Username cannot exceed 20 characters' }),
      password: z.string()
        .min(8, { message: 'Password must be at least 8 characters long' })
        .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, {
          message: 'Password must contain at least one uppercase letter, one lowercase letter, and one number'
        }),
      confirmPassword: z.string(),
    }).refine((data) => data.password === data.confirmPassword, {
      message: "Passwords don't match",
      path: ["confirmPassword"],
    });
    ```
    

## Conclusion

Using React Hook Form with Zod provides a powerful and type-safe way to handle form validation in React applications. This combination offers several benefits:

1. Reduced boilerplate code
    
2. Improved performance with uncontrolled components
    
3. Strong typing and IntelliSense support
    
4. Flexible and extensible validation rules
    

By leveraging these libraries, you can create robust forms with complex validation logic while maintaining clean and maintainable code. As your forms grow in complexity, these tools will help you manage that complexity efficiently.

Remember to always refer to the official documentation of [React Hook Form](https://react-hook-form.com/) and [Zod](https://zod.dev/) for the most up-to-date information and advanced usage scenarios.

![peace out goodbye GIF by Red Bull](https://media2.giphy.com/media/3oEduU0P4xaRiHyGbe/200.gif?cid=ecf05e4708r1xj5dmrsjw602iz20rpa4x7fn36t2xw9ekzyz&ep=v1_gifs_search&rid=200.gif&ct=g align="left")

Keep coding :)

🤖
