FrontendReactReact Hook FormZodTypeScriptForm Validation

React Hook Form and Zod: The Complete Form Validation Guide

Master form validation in React using React Hook Form and Zod schema validation for type-safe, performant forms.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

August 10, 2024 9 min read

Why React Hook Form and Zod?

React Hook Form is the most performant form library for React — it uses uncontrolled components to minimize re-renders. Paired with Zod, a TypeScript-first schema validation library, you get end-to-end type safety from your schema definition to your form state. Together they eliminate the boilerplate of manual validation logic and keep your code clean and maintainable.

Setting Up React Hook Form with Zod

Install the packages: npm install react-hook-form zod @hookform/resolvers. The @hookform/resolvers package bridges Zod schemas with React Hook Form. Define your validation schema using z.object() with Zod validators like z.string().min(1), z.email(), z.number().positive(). Pass the schema to the zodResolver() function and provide it as the resolver option to useForm.

Building Your First Validated Form

Use useForm with your Zod schema to get register, handleSubmit, and formState.errors. Register each input with the register() function and display errors from formState.errors. The handleSubmit wrapper prevents form submission when validation fails and types the data parameter according to your Zod schema automatically.

Advanced Zod Schemas

Zod supports complex validation patterns: z.string().regex() for patterns, z.enum() for allowed values, z.union() for multiple valid types, and z.discriminatedUnion() for conditional schemas. Use .refine() for custom validation logic, such as confirming a password matches its confirmation field. Zod transforms with .transform() let you coerce string inputs to numbers or dates.

Handling Server-Side Errors

After form submission, server validation errors (e.g., 'email already in use') need to be shown to the user. React Hook Form provides setError() to programmatically set errors on specific fields. Call setError('email', { message: 'This email is already registered' }) in your catch block after a failed API call. This keeps the UX consistent between client and server validation.

Performance and Best Practices

React Hook Form avoids unnecessary re-renders by using refs instead of state for most operations. Use the Controller component for third-party inputs like custom date pickers or select dropdowns that don't expose a ref. Keep Zod schemas in separate files and share them between frontend and backend for consistent validation. For large forms, use useWatch selectively to read specific field values without re-rendering the whole form.

Share this article

All posts
#React#React Hook Form#Zod#TypeScript#Form Validation
Abdur Razzak — Full Stack Web Developer

Let's Connect

Follow My Developer Journey