Schema based form validation in React JS using React Hook Form and Zod library
Tags: typescript, react, webdev, opensource
Published: 2023-06-11 17:08:07

## Form Validation

Form validation is an essential aspect of website development that ensures the data entered by users into web forms is accurate, complete, and follows the specified format. It helps maintain data integrity, improves user experience, and prevents potential issues resulting from incorrect or malicious input.

## Zod

The Zod library is a TypeScript-first runtime validation library that provides a simple and expressive way to validate data objects against predefined schemas. It focuses on type safety and usability, making it easier to validate and enforce data integrity in TypeScript projects.

**In ZOD we can only define data constraints such as minLength, maxLength we cannot define field constraints such as reset , required etc..**

## Setup the project

**Create project using vite**

    `npm create vite`

**Enter the application name**

    `Project name: "your application name"`

**Select react form below list**

    `❯ Vanilla
       Vue
       React
       Preact
       Lit
       Svelte
       Others`

**Select the programming language**
In this example i will be using typescript and bootstrap for styling this component 

`❯  TypeScript
    TypeScript + SWC
    JavaScript
    JavaScript + SWC`

**Now execute the following commands one by one to run the application**

` cd summa
  npm install
  npm run dev`

After executing the above steps your application will be running on `localhost:5173`

**The running application will be like this,**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkawvrw37z72updcpb4f.png)

**Before moving on further install the following libraries in your application by using the commands**

`npm install react-hook-form`
`npm i zod`
`npm i @hook-form/resolvers`

_Zod resolvers are used to handle asynchronous validation and transformation of data using the Zod library. While Zod itself provides powerful and flexible schema validation capabilities, it doesn't handle asynchronous operations by default. Zod resolvers fill this gap by providing a convenient way to perform asynchronous validation tasks._

**Create a form component in your application** 
create a basic form in your component

```html
 <form>
      <div className="mb-3">
        <label htmlFor="name" className="form p-3">
          name
        </label>
        <input
          id="name"
          type="text"
          className="form.control"
        />
      </div>
      <div>
        <label htmlFor="age" className="form p-3">
          age
        </label>
        <input
        />
      </div>
      <button className="btn btn-primary mx-3" type="submit">
        Submit
      </button>
    </form>
```

In zod the validation will be done based on the schema we provide. So after creating a form create a schema for the inputs that will be accepted in the form.

**Schema:**_Schemas are nothing but a set of constraints of the type of data that the user will be passing as input in the form.In other words schemas are the datatypes for the from_

In react _Schemas_ should be defined after the import statements in your component.

**Schema declaration for our form**




```typescript
const schema = z.object({
  name: z.string().min(3),
  age: z.number().min(18),
});
```

Define a _Type_ and pass this schema as an _interface_ in the component



`type formData = z.infer<typeof schema>;`







We can define the types of the field data as methods and can also define validation constraints .So that later in form hook we can use this validation as references. 

**Now as the next step use the useForm hook that we installed earlier**




```typescript
const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<formData>({ resolver: zodResolver(schema) });
```




Let's understand whats happening here, the useForm has couple of predefined methods that we destructured as ,

**"register"**- The register method is use to register our form field in the hook so that later we can reference it for validation, this method takes the name attribute of the input tag as an argument 

**"handleSubmit"**- This method takes care of all form submission tasks for us, we only need to simply reference in _onSubmit_ event listener.

**"formState"**- This method keeps track of our form field state and notifies to handle any errors.

Thats enough of the theory stuff, let's see the code in action. 

Define an submit function and call it in handleSubmit() in the form tag.



```typescript
const submit = (data: FieldValues) => {
    console.log(data);
  };
```

`<form onSubmit={handleSubmit(submit)}>`


**Use the register method in the input tag and set validation conditions such as 'required'**


`{...(register("name"), { required: true})}`


**In zod we can also display custom Error messages or default messages that are predefined in the zod library**

We can do this by using simple logic as ,

`{errors.name && <p>{errors.name.message}</p>}`

And finally, after all the above steps are implemented the final code looks like this,




```html
import { useForm, FieldValues } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

const schema = z.object({
  name: z.string().min(3),
  age: z.number().min(18),
});

type formData = z.infer<typeof schema>;

const form = () => {
const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<formData>({ resolver: zodResolver(schema) });

  const submit = (data: FieldValues) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(submit)}>
      <div className="mb-3">
        <label htmlFor="name" className="form p-3">
          name
        </label>
        <input
            {...(register("name"), { required: true})}

     id="name"
          type="text"
          name=""
          className="form.control"
        />
        {errors.name && <p>{errors.name.message}</p>}
     </div>
      <div>
        <label htmlFor="age" className="form p-3">
          age
        </label>
        <input
          {...register("age")}
         id="age"
          type="number"
          className="form.control"
        />
</div>
      <button className="btn btn-primary mx-3" type="submit">
        Submit
      </button>
    </form>
  );
};

export default form;

```

Thats all it takes to create a form with schema based validation using react-hook-form and zod library.