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:
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
// 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;
// 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: