Validating your React Forms with Zod and no-hooks


3 min read

Play this article

Guys, I read this amazing tweet today and this blew my mind ๐Ÿคฏ, I am not sure if this is the optimal way to do this but I just felt to document this.

Here is the original tweet ๐Ÿ‘‡

Setting Up a CRA and creating a form

I am just gonna get ahead and create a simple form, the basic barebone and structure using JSX

import "./styles.css";

export default function App() {

  return (
    <div className="App">
      <form className="form" onSubmit={handleSubmit}>
          <label for="firstName"> First name : </label>
          <label for="lastName"> last name : </label>
          <input name="lastName" type="text" placeholder="Doe" />
          <label htmlFor="email"> email : </label>
          <label for="password"> Password : </label>

          <input name="password" type="password" placeholder="********" />
          <label for="confirm password"> Confirm Password : </label>


Preview :


Once this is done your basic non-styled form will look something like this and all you need is to get the user data from the From.

let's create a handle submit function now, if you know react this will be very easy for you but here it goes.

const handleSubmit = (e) => {
    const formData = new FormData(;
    const data = Object.fromEntries(formData);

so what is happening here is we are getting the form element and creating a new Form Data once that is done we are converting it into Objects using the javascript method Object.fromEntries(formData)

Once that is done let's test our App so far. formWithZod.gif

Installing and Validating Zod

npm i zod

  // or

yarn add zod

once Zod is installed let's define our schema for the form inputs and then we will try to validate it. In my use case, we will be adding only for firstName, lastName, email, password and confirmPassword.

const validateSchema = z
      firstName: z.string().min(3),
      lastName: z.string(),
      email: z.string().email(),
      password: z.string().min(6),
      confirmPassword: z.string().min(6)
    .refine((data) => data.password === data.confirmPassword, {
      message: "Password doesn't match",
      path: ["confirmpassword"]

this is a schema on that basis we will be validating our form like below and our new handle submit will look something like this. Now you can add different validation and show the user error message and handle logic of what to do after submitting.

const handleSubmit = (e) => {
    const formData = new FormData(;
    const data = Object.fromEntries(formData);
    try {
      const validatedForm = validateSchema.parse(data);
    } catch (err) {
    // console.log(data);

Here is our completed App

Try this out :P

Did you find this article valuable?

Support Ashish maurya by becoming a sponsor. Any amount is appreciated!