Mastering Form Validation with Zod, TypeScript, and React Hook Form

In the vast world of web development, TypeScript and React Hook Form are like superheroes teaming up to save the day. But every superhero needs some powerful tools, and that's where the Zod package comes into play. In this blog post, we'll explore how Zod, TypeScript, and React Hook Form join forces to create robust and type-safe forms in your React applications.

What is Zod? Zod is a TypeScript-first schema declaration and validation library. Think of it as a guard at the gate of your application, ensuring that the data entering and leaving is exactly what you expect. It's like a bouncer for your data, making sure only the right types get past.

Why TypeScript? Before diving into Zod, let's quickly revisit TypeScript. TypeScript adds static types to JavaScript, making your code more predictable and less error-prone. When working with forms, having a clear understanding of the data structure is crucial, and TypeScript helps achieve just that.

Setting the Stage with React Hook Form: React Hook Form is a fantastic library for managing forms in React applications. It provides a simple and performant way to handle form state and validation. Integrating Zod with React Hook Form gives us an extra layer of confidence in our forms.

Installing Zod: To get started, install Zod using your favorite package manager:

npm install zod
# or
yarn add zod

Defining Form Schema with Zod: Now, let's create a Zod schema for our form data. This schema acts as a blueprint, specifying the shape and types of our data. For example:

import { z } from 'zod';

const userSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.string().email(),
});

Here, we've defined a schema for a user with a name (string), age (number), and email (string with email format).

Integrating Zod with React Hook Form: With our schema in place, let's use it with React Hook Form:

import { useForm } from 'react-hook-form';

const MyForm = () => {
  const { register, handleSubmit, errors } = useForm({
    resolver: async (data) => {
      try {
        // Validate data against the Zod schema
        await userSchema.validate(data);
        return { values: data, errors: {} };
      } catch (error) {
        // Handle validation errors
        return { values: {}, errors: error.errors };
      }
    },
  });

  const onSubmit = (data) => {
    // Handle form submission
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>Name</label>
      <input {...register('name')} />
      {errors.name && <p>{errors.name.message}</p>}

      <label>Age</label>
      <input type="number" {...register('age')} />
      {errors.age && <p>{errors.age.message}</p>}

      <label>Email</label>
      <input type="email" {...register('email')} />
      {errors.email && <p>{errors.email.message}</p>}

      <button type="submit">Submit</button>
    </form>
  );
};

Understanding more about Zod Schema: Zod schemas act as blueprints for our form data. Let's expand on our user schema to include required fields and custom error messages:

import { z } from 'zod';

const userSchema = z.object({
  name: z.string().min(2, { message: 'Name must be at least 2 characters' }),
  age: z.number().int().positive(),
  email: z.string().email({ message: 'Invalid email format' }),
});

Here, we've added constraints like minimum length for the name, ensuring the age is a positive integer, and providing custom error messages for better user feedback.

Making Fields Required: To mark a field as required, use the required() method:

const userSchema = z.object({
  name: z.string().min(2, { message: 'Name must be at least 2 characters' }).required(),
  age: z.number().int().positive().required(),
  email: z.string().email({ message: 'Invalid email format' }).required(),
});

Conclusion:
And there you have it! By combining Zod with TypeScript and React Hook Form, you've built a fortress of type safety and validation around your forms. Now, go ahead and create amazing, bug-free forms with the confidence that comes from the dynamic trio of Zod, TypeScript, and React Hook Form. Happy coding!


Did you find this article valuable?

Support Nitesh Singh by becoming a sponsor. Any amount is appreciated!