How To Implement NextJS Form Validation With Formik And Zod ?

Form validation is a critical aspect of web development to ensure that user input meets specific criteria before submitting data to the server. Implementing form validation in Next.js can be simplified using Formik, a form library for React, and Zod, a schema validation library. Together, they provide a robust solution for managing form state and validating input data in Next.js applications.

Prerequisites:

Approach to Implement NextJS Form Validation with Formik and Zod

  • Define the layout and structure of the login form using React components and Formik library.
  • Specify validation rules for form fields using Zod schema. This includes requirements for the name, email, and message fields.
  • Display form fields and error messages dynamically.
  • Connect validation schema with Formik.
  • When the button is clicked, Formik invokes the onSubmit function, triggering the defined actions such as displaying an alert.

Step 1: Create a NextJS application

npx create-next-app <-ProjectName->

Step 2: Navigate to the Project directory

cd <-ProjectName->

Step 3: Install necessary dependencies and bootstrap for CSS styling.

npm install formik zod zod-formik-adapter  bootstrap

Project Structure:

Project Structure

The Updated dependencies in your package.json file is look like:

"dependencies": {
"bootstrap": "^5.3.3",
"formik": "^2.4.6",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
"zod": "^3.23.8",
"zod-formik-adapter": "^1.3.0"
},

Step 4: Create a folder as components and make a components as LoginForm.tsx

JavaScript
// src/app/components/LoginForm.tsx
import React from "react";
import { TypeOf, object, string } from "zod";
import { Formik, Form, Field } from "formik";
import { toFormikValidationSchema } from "zod-formik-adapter";

type ContactFormInputs = TypeOf<typeof contactFormSchema>

const contactFormSchema = object({
  name: string({
    required_error: "Please enter your name",
  }),
  email: string().email("Please enter a valid email"),
  message: string().min(50).max(1000),
});

const LoginForm = () => {
  return (
    <>
      <Formik<ContactFormInputs>
        initialValues={{
          name: "",
          email: "",
          message: "",
        }}
        onSubmit={(values) => {
          alert("Form is submitted")
          console.log("Form is submitted", values);
        }}
        validationSchema={toFormikValidationSchema(contactFormSchema)}
      >{
          (FormikState) => {
            const errors = FormikState.errors;
            return (
              <div className="card shadow">
                <Form className="card-body">
                  <div className="card-title">Contact Us</div>
                  <div className="d-flex justify-content-between gap-2">
                    <div className="form-group w-100">
                      <label className="form-label">
                        <span className="label-text">Your name</span>
                      </label>
                      <Field
                        type="text"
                        name="name"
                        placeholder="e.g. John Doe"
                        className="form-control"
                      />{!!errors.name && (
                        <div className="form-text text-danger">
                          {errors.name}
                        </div>
                      )}

                    </div>
                    <div className="form-group w-100">
                      <label className="form-label">
                        <span className="label-text">Your email</span>
                      </label>
                      <Field
                        type="text"
                        name="email"
                        placeholder="e.g johndoe@gmail.com"
                        className="form-control"
                      />
                      {!!errors.email && (
                        <div className="form-text text-danger">
                          {errors.email}
                        </div>
                      )}

                    </div>
                  </div>
                  <div className="form-group">
                    <label className="form-label">
                      <span className="label-text">Your message</span>
                    </label>
                    <Field
                      as="textarea"
                      type="text"
                      name="message"
                      className="form-control h-24"
                      placeholder="Message"
                    />
                    {!!errors.message && (
                      <div className="form-text text-danger">
                        {errors.message}
                      </div>
                    )}

                  </div>
                  <div className="card-actions justify-content-end">
                    <button className="btn btn-primary" type="submit">
                      Submit
                    </button>
                  </div>
                </Form>
              </div>
            )
          }
        }
      </Formik>

    </>
  );
};

export default LoginForm;
JavaScript
// page.js
'use client';
import "bootstrap/dist/css/bootstrap.min.css";
import LoginForm from './components/LoginForm.tsx';
import React from 'react';

export default function Home() {
    return (
        <div className="container">
            <div className="row justify-content-center 
                        align-items-center min-vh-100">
                <div className="col-md-6">
                    <h1 className="text-center mb-4">
                        Welcome to Zod + Formik Tutorial
                    </h1>
                    <LoginForm />
                </div>
            </div>
        </div>
    );
}

Start your application using the following command:

npm run dev

Output:

Validation using formik and zod



Contact Us