DEV Community

Cover image for Using Zod with React hook form using typescript
Majiedo
Majiedo

Posted on

Using Zod with React hook form using typescript

Hi, if your application uses some sort of API is MUST to have some validation before sending any request! for example if you have simple sign up page where you have email field and password and let's imagine if user typed something like this in the email field "HelloWorld" this is clearly isn't an email even if our API will throw some kind of error saying " the email field should be an email " the time a request go and response get back where's clearly will throw an error not worth the time in my opinion validation should be on both ways frontend and backend so what should we do? well first we need to install zod and react hook form!

npm install react-hook-form zod @hookform/resolvers

now after installing them we make schema for our form

import { z } from 'zod';

const SignUpSchema = z.object({
  email: z.string().email(),
  password: z
    .string()
    .min(3)
    .max(20)
});

type SignUpSchemaType = z.infer<typeof SignUpSchema>;
Enter fullscreen mode Exit fullscreen mode

so now in our schema we said the email must be an string and email and our password must be a string and min 3 characters and max 20

so now we go to our form component we create simple form

export default function App() {
  return (
    <form  className="form">
      <input className="input" placeholder="email" />
      <input
        className="input"
        placeholder="password"
      />
      <button type="submit">submit!</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

now we simple add the useForm hook from the react-hook-form

import { useForm } from "react-hook-form";
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm<SignUpSchemaType>({ resolver: zodResolver(SignUpSchema) });
Enter fullscreen mode Exit fullscreen mode

and the hook will take an object that resolver going to be from (@hookform/resolvers) which is zodResolver!

now we're ready to add connect the inputs to the hook by the register!

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm<SignUpSchemaType>({ resolver: zodResolver(SignUpSchema) });



  return (
    <form className="form">
      <input className="input" placeholder="email" {...register("email")} />


      <input
        className="input"
        placeholder="password"
        {...register("password")}
      />


      <button type="submit">submit!</button>
    </form>
  );
}

Enter fullscreen mode Exit fullscreen mode

now whenever we type into these to fields the useForm will fire!

so now we want to show the error message below each input to show the error if there's an error like our example if we put in the email field "HelloWorld"

here how we do it by the form state the errors!

 return (
    <form className="form">
      <input className="input" placeholder="email" {...register("email")} />
      {errors.email && <span>{errors.email.message}</span>}

      <input
        className="input"
        placeholder="password"
        {...register("password")}
      />

      {errors.password && <span>{errors.password.message}</span>}

      <button type="submit">submit!</button>
    </form>
  );
Enter fullscreen mode Exit fullscreen mode

now when we have error on password or email fields will show the span

Errors

so now we need to handle when the button clicked on submit

so first we create a simple function will only fire when all validation success!

//we should here call like API or something...
  const onSubmit: SubmitHandler<SignUpSchemaType> = (data) => console.log(data);
Enter fullscreen mode Exit fullscreen mode

and now we add a simple onSubmit to our form and we call handleSubmit from useForm hook like this

    <form onSubmit={handleSubmit(onSubmit)} className="form">

Enter fullscreen mode Exit fullscreen mode

so now we have our validation before sending it to some API

Errors

here's the full code

import "./styles.css";
import { z } from "zod";
import { useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

const SignUpSchema = z.object({
  email: z.string().email(),
  password: z.string().min(3).max(20)
});
type SignUpSchemaType = z.infer<typeof SignUpSchema>;

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm<SignUpSchemaType>({ resolver: zodResolver(SignUpSchema) });

  //we should here call like API or something...
  const onSubmit: SubmitHandler<SignUpSchemaType> = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="form">
      <input className="input" placeholder="email" {...register("email")} />
      {errors.email && <span>{errors.email.message}</span>}

      <input
        className="input"
        placeholder="password"
        {...register("password")}
      />

      {errors.password && <span>{errors.password.message}</span>}

      <button type="submit">submit!</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

and there's a lot to do with zod and use form hook you can look at the documentation react hook form zod and shout-out to Austin Shelby for great video

Thank you for giving your time to read this simple post!

Top comments (0)