Using Zod with React hook form using typescript

Forms are an essential part of web development, and React provides powerful tools for managing them efficiently. However, as forms grow in complexity, managing validation, state, and user interaction becomes increasingly challenging. In this advanced guide, we’ll explore how to build robust React forms with ease, leveraging the capabilities of Zod for streamlined validation.

Understanding the Challenge

When it comes to building forms in React, several challenges commonly arise:

  1. State Management: Handling form state can become complex, especially for large forms with multiple input fields. React’s component state or state management libraries like Redux can help manage this complexity.
  2. Validation: Ensuring that user input meets specific criteria, such as required fields, valid email addresses, or minimum character lengths, can be cumbersome. Validating user input is crucial for data integrity and preventing errors.
  3. Error Handling: Providing meaningful feedback to users when form submission fails due to validation errors is essential for a good user experience. Clear error messages help users understand and correct their mistakes.
  4. Integration with External Libraries: Integrating with third-party libraries for form validation often requires additional setup and can lead to integration issues. Choosing the right validation library can simplify this process and improve development efficiency.

Introducing Zod

Zod is a TypeScript-first schema declaration and validation library. It allows you to define schemas for your data structures and provides powerful validation capabilities out of the box. Integrating Zod with React forms simplifies the validation process and ensures type safety throughout your application.

Building a React Form with Zod

Let’s dive into building a React form with Zod step by step:

Step 1: Install Zod

The first step is to install Zod in your project. You can do this via npm or yarn:

npm install zod

Step 2: Define a Schema with Zod

Before creating the form component, define a schema for your form data using Zod. A schema defines the shape and validation rules for your data. For example:

import { z } from 'zod';

const LoginFormSchema = z.object({
  username: z.string().min(3),
  password: z.string().min(6),
});

Step 3: Create a React Form Component

Now, create a React component for your form. This component will manage the form state, handle user input, and display validation errors. Here’s a simple example:

import React, { useState } from 'react';
import { z } from 'zod';

// Define schema with Zod
const LoginFormSchema = z.object({
  username: z.string().min(3),
  password: z.string().min(6),
});

const LoginForm = () => {
  const [formData, setFormData] = useState({
    username: '',
    password: '',
    confirmPassword: '',
  });
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    try {
      // Validate form data against schema
      const validatedData = LoginFormSchema.parse(formData);

      // Check password confirmation
      if (validatedData.password !== formData.confirmPassword) {
        throw new Error("Passwords don't match");
      }

      // Form data is valid, proceed with submission
      console.log('Form submitted:', formData);
    } catch (error) {
      // Validation failed, update error state
      if (error instanceof z.ZodError) {
        const validationErrors = {};
        error.errors.forEach((err) => {
          const path = err.path.join('.');
          validationErrors[path] = err.message;
        });
        setErrors(validationErrors);
      } else {
        // Handle password mismatch error
        setErrors({ confirmPassword: error.message });
      }
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Username:</label>
        <input
          type="text"
          name="username"
          value={formData.username}
          onChange={handleChange}
        />
        {errors.username && <span>{errors.username}</span>}
      </div>
      <div>
        <label>Password:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
        {errors.password && <span>{errors.password}</span>}
      </div>
      <div>
        <label>Confirm Password:</label>
        <input
          type="password"
          name="confirmPassword"
          value={formData.confirmPassword}
          onChange={handleChange}
        />
        {errors.confirmPassword && <span>{errors.confirmPassword}</span>}
      </div>
      <button type="submit">Submit</button>
    </form>
  );
};

export default LoginForm;

Step 4: Integrate Zod Validation

In the handleSubmit function, use LoginFormSchema.parse to validate the form data against the defined schema. If validation fails, Zod will throw an error containing validation messages, which can be displayed to the user.

Step 5: Refining Validation with Zod

Zod provides a powerful method called .refine() that allows you to add custom validation rules beyond what the basic schema methods offer. This is particularly useful for cases like password confirmation, where you need to compare two fields. Let’s see how we can use .refine() to enhance our form validation.

const LoginFormSchema = z.object({
  username: z.string().min(3),
  password: z.string().min(6),
  confirmPassword: z.string(),
}).refine(data => data.password === data.confirmPassword, {
  message: "Passwords don't match",
  path: ['confirmPassword'],
});

By refining our validation with Zod’s .refine() method, we can easily implement custom validation rules and provide a better user experience with meaningful error messages.

Conclusion

Building advanced React forms doesn’t have to be daunting. By leveraging Zod for schema-based validation, you can streamline the form development process, ensure data integrity, and provide a seamless user experience. Experiment with different features and explore the possibilities of React forms empowered by Zod!

Next Post Previous Post
No Comment
Add Comment
comment url