Forms with Zod Validation in Next.js

Binay MaharjanBinay Maharjan
3 min read

Forms are a common feature in web applications. They are used to collect user input and submit it to a server. However, it is important to validate form data before submitting it to ensure it is accurate and complete. We will show you how to create forms with validation in Next.js using Zod, React Hook Form, and Zod Resolver. For the UI parts of forms, we choose Shadcn which is not a component library but It's a collection of reusable components that you can copy and paste into your apps

What is Zod?

Zod is a powerful TypeScript validation library that provides a simple and intuitive way to define and validate data structures. It is designed to work seamlessly with TypeScript's type system, offering type safety and reducing the likelihood of runtime errors. Learn more

What is React Hook Form?

React Hook Form is a library that simplifies form handling in React by providing custom hooks and utility functions. It offers features such as controlled inputs, validation, and form submission. Learn more

What is Zod Resolver?

Zod Resolver is a utility library that integrates Zod schemas with React Hook Form, providing a seamless way to validate form data using Zod. Learn more

How to Create a Form with Validation in Next.js

  1. Create a new Next.js project or an existing Next.js project.
    Install these packages

     npm install react-hook-form //Installing React Hook Form
     npm install zod // Installing zod package
     npm install @hookform/resolvers //Installing React Hook Form resolveInstall  Zod, React Hook Form, and Zod Resolver.
    
  2. Create a new component called basic-form.tsx which contains the form and inputs. We use Shadcn ui for the form elements. To get work of this basic form we have to install shadcn first and then form, input, and button. Like
    npm install shadcn init
    npm install form input button

     "use client"
     import {
       Form,
       FormControl,
       FormField,
       FormItem,
       FormLabel,
     } from "@/components/ui/form"
     import { Input } from "@/components/ui/input"
     import { Button } from "@/components/ui/button"
    
     export function BasicForm() {
       return (
         <Form {...form}>
           <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
             <FormField
               control={form.control}
               name="name"
               render={({ field }) => (
                 <FormItem>
                   <FormLabel>Name</FormLabel>
                   <FormControl>
                     <Input placeholder="Enter name" {...field} />
                   </FormControl>
                 </FormItem>
               )}
             />
              <FormField
                   control={form.control}
                   name="email"
                   render={({ field }) => (
                     <FormItem>
                       <FormLabel>Email</FormLabel>
                       <FormControl>
                         <Input placeholder="Enter email" {...field} />
                       </FormControl>
                     </FormItem>
                   )}
                 />
              <FormField
                   control={form.control}
                   name="password"
                   render={({ field }) => (
                     <FormItem>
                       <FormLabel>Password</FormLabel>
                       <FormControl>
                         <Input type="password" placeholder="Enter Password" {...field} />
                       </FormControl>
                     </FormItem>
                   )}
                 />
             <Button type="submit">Submit</Button>
           </form>
         </Form>
       )
     }
    
  3. Define a Zod schema for the form data.

     const formSchema = z.object({
       name: z.string().min(2),
       email: z.string().email(),
       password: z.string().min(6),
     })
    
  4. Integrate the Zod schema with React Hook Form using Zod Resolver.

     const form = useForm<z.infer<typeof formSchema>>({
             resolver: zodResolver(formSchema),
             defaultValues: {
                 name:'',
                 email:'example@gmail.com', //we can give default values too
                 password:''
             }
     })
    
  5. Add error messages to the form to display validation errors.

     const formSchema = z.object({
       name: z.string().min(2,{
         message: "Name must be at least 2 characters.",
       }),
       email: z.string().email({
         message: "Please enter a valid email address"
         }),
       password: z.string().min(6,{
         message: "Password must be of 6 character"
         }),
     })
    
  6. Submit the form and handle the response.

      const onSubmit = (data: z.infer<typeof formSchema>) => {
             console.log(data)        
         };
    
  7. Here is the working example

    https://codesandbox.io/p/devbox/zod-form-validation-vh9h9w

Conclusion

By leveraging Zod, Next.js, React Hook Form, Zod Resolver, and Shadcn, you can create robust, efficient, and visually appealing forms in your Next.js applications. This powerful combination provides a solid foundation for building high-quality user experiences.Thank you.

References

https://react-hook-form.com/docs/useform#resolver

https://react-hook-form.com/get-started

https://zod.dev/?id=introduction

https://www.freecodecamp.org/news/react-form-validation-zod-react-hook-form/

https://dev.to/majiedo/using-zod-with-react-hook-form-using-typescript-1mgk

2
Subscribe to my newsletter

Read articles from Binay Maharjan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Binay Maharjan
Binay Maharjan

๐Ÿ‘‹ Hello World! I'm Binay Maharjan, a passionate Front-End Developer the ever-evolving realm of web development. ๐Ÿš€ ๐ŸŒˆ Design Enthusiast: With an eye for aesthetics, I bring designs to life, ensuring a seamless fusion of form and function. My CSS skills extend to animations, transitions, and the art of making websites not just functional, but delightful. ๐Ÿ“ Responsive Design Advocate: From desktops to tablets and smartphones, I'm dedicated to creating websites that adapt flawlessly to every screen size. A user-centric approach guides my responsive design philosophy. โš™๏ธ Tech Innovator: I thrive on staying up-to-date with the latest trends and emerging technologies in the front-end development landscape. Constantly refining my skills to implement cutting-edge solutions, I am committed to delivering high-quality, forward-thinking code.