DEV Community

Suresh Hariharan
Suresh Hariharan

Posted on

Schema based form validation in React JS using React Hook Form and Zod library

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 fullscreen mode Exit fullscreen mode

Enter the application name

`Project name: "your application name"`
Enter fullscreen mode Exit fullscreen mode

Select react form below list

`❯ Vanilla
   Vue
   React
   Preact
   Lit
   Svelte
   Others`
Enter fullscreen mode Exit fullscreen mode

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

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

 <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>
Enter fullscreen mode Exit fullscreen mode

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

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

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

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

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.

const submit = (data: FieldValues) => {
    console.log(data);
  };
Enter fullscreen mode Exit fullscreen mode

<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,

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;

Enter fullscreen mode Exit fullscreen mode

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

Top comments (1)

Collapse
 
priyadharshan_senthil_2e1 profile image
Priyadharshan senthil

Very useful technique for validating form...👍🏻