Home

Using Zod in a Normal Form Validation in Next.js

Medium
Next.jsZod

First of all, if you don't know what Zod is, don't worry, hold on a bit here.

Setting the environment (mindset)

What we normally do is use <form> and <input> to create a normal form UI. This is fine for normal. But how can we validate the input data? Think???

Yes, there are tons of ways. Either manually, or we can use the inbuilt options like required or minval but there is a better approach, which is Zod.

I won't go into the theory of it, because I don't want to waste time explaining what's already there on the web. So let's implement Zod in the most basic way.

The form

So we have a form like this:

<form onSubmit={handlesubmit} className="flex flex-col w-fit space-y-3">
  <div className=" flex items-center gap-2">
    <input
      type="text"
      placeholder="Enter the name"
      className="inputstyle flex-1"
      name="username"
      value={formdata.username}
      onChange={handlechange}
    />
  </div>
</form>

Here is a typical form. We have values which are coming from a state (structured in an object way, you can make them individually).

Now you can see two functions called: handlechange and handlesubmit. Let's see these two functions one by one.

handlechange

const handlechange = (e) => {
  const { name, value } = e.target;
  setformdata({ ...formdata, [name]: value });
};

The handlechange is a typical function where we take in the value and set the formdata. Here we have used the spread operator so the data doesn't get lost.

handlesubmit

const handlesubmit = (e) => {
  e.preventDefault();
  try {
    userSchema.parse(formdata); //zod
    seterrors({});
    //sending form to backend
    console.log("form data: ", formdata);
  } catch (error) {
    if (error instanceof z.ZodError) {
      const errorObj = {};
      error.errors.forEach((error) => {
        errorObj[error.path[0]] = error.message;
      });
      seterrors(errorObj);
    }
  }
};

Firstly, remove the default behavior. Then, using the try/catch block, we do the schema validation, the parse function is used. (We will see the userSchema soon.)

If this passes, we can set the errors to empty and then start passing it to the backend or anywhere. But if there's an error (typically a failure in validation), we set the error object to the error and print it to the screen.

Declaring the userSchema

import { z } from "zod";

export const userSchema = z.object({
  username: z.number().optional(),
  password: z.string().min(12),
});

Zod is powerful and easy. Here I have just used number to show in the example. We have many other functions like max, nullable and many more.

Wrapping up

Even though it is simple, many developers sometimes get overwhelmed by the many possibilities like this. We can use React Hook Form and many other things too.

So keep learning, and signing off.