Form validation in Next.js using Formik and Yup

Let's build a simple signup form in Next.js using Formik and Yup. We will validate the form using Yup and display the errors using Formik.

Install Formik and Yup

npm install formik --save
npm install yup --save

Create a signup form with 3 fields: name, email, and password.

We will use Formik to handle the form state and Yup to validate the form.

import type { NextPage } from "next";
import { useFormik } from "formik";
import * as Yup from "yup";

// Yup schema to validate the form
const schema = Yup.object().shape({
  name: Yup.string().required(),
  email: Yup.string().required().email(),
  password: Yup.string().required().min(7),
});

const Signup: NextPage = () => {
  // Formik hook to handle the form state
  const formik = useFormik({
    initialValues: {
      name: "",
      email: "",
      password: "",
    },

    // Pass the Yup schema to validate the form
    validationSchema: schema,

    // Handle form submission
    onSubmit: async ({ name, email, password }) => {
      // Make a request to your backend to store the data
    },
  });

  // Destructure the formik object
  const { errors, touched, values, handleChange, handleSubmit } = formik;

  return (
    <form onSubmit={handleSubmit} method="POST">
      <label htmlFor="name">Name</label>
      <input
        type="text"
        name="name"
        value={values.name}
        onChange={handleChange}
        id="name"
      />
      {errors.name && touched.name && <span>{errors.name}</span>}

      <label htmlFor="email">Email</label>
      <input
        type="email"
        name="email"
        value={values.email}
        onChange={handleChange}
        id="email"
      />
      {errors.email && touched.email && <span>{errors.email}</span>}

      <label htmlFor="password">Password</label>
      <input
        type="password"
        name="password"
        value={values.password}
        onChange={handleChange}
        id="password"
      />
      {errors.password && touched.password && <span>{errors.password}</span>}

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

export default Signup;

The below code snippet check whether the error exists and if the field has been touched. If both conditions are true, then it displays the error message.

errors.name && touched.name && <span>{errors.name}</span>;

You can customize the error message by passing a string to the rules.

Here is an example of a custom error message for the email field.

const schema = Yup.object().shape({
  email: Yup.string().required("Email is required").email("Invalid email"),
});

Find an example on GitHub