How to build a Contact form with Formik in Next JS and TypeScript
Tags: nextjs, react, javascript, webdev
Published: 2021-12-28 18:07:02

---
title: How to build a Contact form with Formik in Next JS and TypeScript
published: true
description: Building a form in Next can be difficult, mostly when the form is complex. Using Formik, it's possible to quickly create simple forms whatever the complexity.
tags: Nextjs, react, javascript, webdev
cover_image: https://creativedesignsguru.com/assets/images/themes/next-js-form-formik-contact.png
canonical_url: https://creativedesignsguru.com/next-js-formik/
---

In this article, we'll learn how to build a form using Next, TypeScript, and Formik. We'll be building a simple contact form with basic validation before submitting it. Formik is flexible library for building forms in React and React Native.

## Set up project

Let's create the project for this tutorial. Open your terminal and enter the following command.

```shell
npx create-next-app@latest --ts nextjs-formik-demo
```

This will create a next project based on TypeScript. Here, I've named the project `nextjs-formik-demo`.
Once the project initialization is done, go to the project directory and run the development server.

```shell
cd nextjs-formik-demo
npm run dev
```

Your server will normally be running on http://localhost:3000.

![Next TypeScript index development page](https://creativedesignsguru.com/assets/images/themes/next-js-typescript-index-page.png)

Great, let's now modify the `index.tsx` file and create the form.

## Creating the form

Before going further, let's install the `bootstrap` UI package. It'll be very useful to quickly create a form. We'll also install `formik` and `yup`.

```shell
npm install bootstrap formik yup
```

Once it's done go to `index.tsx` file and let's start modifying it.
First of all, let's import the packages we'll be using.

```tsx
import { useState } from 'react';

import { useFormik } from 'formik';
import * as yup from 'yup';

import 'bootstrap/dist/css/bootstrap.min.css';
...
```

- **useState**: a hook that allows you to have state variables in functional components
- **Formik**: a React package that helps in forms creation, validation, and submission.
- **Yup**: a JavaScript schema builder for value parsing and validation
- **bootstrap**: we are directly importing the CSS files so we can use bootstrap CSS classes to style our components.

Next step, let's create values and object we'll be using for the next steps.

```tsx
...
import type { NextPage } from 'next';

const Home: NextPage = () => {
  const [message, setMessage] = useState(''); // This will be used to show a message if the submission is successful
  const [submitted, setSubmitted] = useState(false);

  const formik = useFormik({
    initialValues: {
      email: '',
      name: '',
      message: '',
    },
    onSubmit: () => {
      setMessage('Form submitted');
      setSubmitted(true);
    },
    validationSchema: yup.object({
      name: yup.string().trim().required('Name is required'),
      email: yup
        .string()
        .email('Must be a valid email')
        .required('Email is required'),
      message: yup.string().trim().required('Message is required'),
    }),
  });
...
```

What are we doing here?

- **message** & **submitted**: This will help show a message that will be displayed when the form is successfully submitted
- **formik**: we use the `useFormik` hooks to create a **Formik** object. It contains the initial values, the `onSubmit` method followed by a validation schema `validationSchema` built with `Yup`.

It's basically all we need for a form in just a few lines. Let's move to the UI and start using the `formik` object.

```tsx
...
<div className="vh-100 d-flex flex-column justify-content-center align-items-center">
  <div hidden={!submitted} className="alert alert-primary" role="alert">
    {message}
  </div>

  <form className="w-50" onSubmit={formik.handleSubmit}>
    {/* Adding the inputs */}
  </form>
</div>
...
```

We want to display an alert every time the form is successfully submitted. That's what this piece of code achieves:

```tsx
<div hidden={!submitted} className="alert alert-primary" role="alert">
  {message}
</div>
```

We can now add the inputs. For each input, we'll be adding the label, the input and the error message for each field.
Let's start with the `name` field.

```tsx
<form className="w-50" onSubmit={formik.handleSubmit}>
  <div className="mb-3">
    <label htmlFor="name" className="form-label">
      Name
    </label>
    <input
      type="text"
      name="name"
      className="form-control"
      placeholder="John Doe"
      value={formik.values.name}
      onChange={formik.handleChange}
      onBlur={formik.handleBlur}
    />
    {formik.errors.name && (
      <div className="text-danger">{formik.errors.name}</div>
    )}
  </div>
  ...
</form>
```

And then the `email` field.

```tsx
<form className="w-50" onSubmit={formik.handleSubmit}>
  ...
  <div className="mb-3">
    <label htmlFor="email" className="form-label">
      Email
    </label>
    <input
      type="email"
      name="email"
      className="form-control"
      placeholder="john@example.com"
      value={formik.values.email}
      onChange={formik.handleChange}
      onBlur={formik.handleBlur}
    />
    {formik.errors.email && (
      <div className="text-danger">{formik.errors.email}</div>
    )}
  </div>
  ...
</form>
```

And next, the `message` field.

```tsx
<form className="w-50" onSubmit={formik.handleSubmit}>
  ...
  <div className="mb-3">
    <label htmlFor="message" className="form-label">
      Message
    </label>
    <textarea
      name="message"
      className="form-control"
      placeholder="Your message ..."
      value={formik.values.message}
      onChange={formik.handleChange}
      onBlur={formik.handleBlur}
    />
    {formik.errors.message && (
      <div className="text-danger">{formik.errors.message}</div>
    )}
  </div>
  ...
</form>
```

And finally the submit button.

```tsx
<form className="w-50" onSubmit={formik.handleSubmit}>
  ...
  <button type="submit" className="btn btn-primary">
    Send
  </button>
</form>
```

And here's the final code of the form.

```tsx
<div className="vh-100 d-flex flex-column justify-content-center align-items-center">
  <div hidden={!submitted} className="alert alert-primary" role="alert">
    {message}
  </div>

  <form className="w-50" onSubmit={formik.handleSubmit}>
    <div className="mb-3">
      <label htmlFor="name" className="form-label">
        Name
      </label>
      <input
        type="text"
        name="name"
        className="form-control"
        placeholder="John Doe"
        value={formik.values.name}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />
      {formik.errors.name && (
        <div className="text-danger">{formik.errors.name}</div>
      )}
    </div>

    <div className="mb-3">
      <label htmlFor="email" className="form-label">
        Email
      </label>
      <input
        type="email"
        name="email"
        className="form-control"
        placeholder="john@example.com"
        value={formik.values.email}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />
      {formik.errors.email && (
        <div className="text-danger">{formik.errors.email}</div>
      )}
    </div>

    <div className="mb-3">
      <label htmlFor="message" className="form-label">
        Message
      </label>
      <textarea
        name="message"
        className="form-control"
        placeholder="Your message ..."
        value={formik.values.message}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />
      {formik.errors.message && (
        <div className="text-danger">{formik.errors.message}</div>
      )}
    </div>

    <button type="submit" className="btn btn-primary">
      Send
    </button>
  </form>
</div>
```

And the form is operational now. If you noticed, we are conditionally showing errors in the forms using `formik.errors`.

```tsx
{formik.errors.name && (
  <div className="text-danger">{formik.errors.name}</div>
)}
```

This will display an error under the `name` field for example.

![Next JS Formik Error message](https://creativedesignsguru.com/assets/images/themes/next-js-formik-error-message.png)

Here's the final code for `index.tsx`.

```tsx
import { useState } from 'react';

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

import 'bootstrap/dist/css/bootstrap.min.css';

const Home: NextPage = () => {
  const [message, setMessage] = useState(''); // This will be used to show a message if the submission is successful
  const [submitted, setSubmitted] = useState(false);

  const formik = useFormik({
    initialValues: {
      email: '',
      name: '',
      message: '',
    },
    onSubmit: () => {
      setMessage('Form submitted');
      setSubmitted(true);
    },
    validationSchema: yup.object({
      name: yup.string().trim().required('Name is required'),
      email: yup
        .string()
        .email('Must be a valid email')
        .required('Email is required'),
      message: yup.string().trim().required('Message is required'),
    }),
  });

  return (
    <div className="vh-100 d-flex flex-column justify-content-center align-items-center">
      <div hidden={!submitted} className="alert alert-primary" role="alert">
        {message}
      </div>

      <form className="w-50" onSubmit={formik.handleSubmit}>
        <div className="mb-3">
          <label htmlFor="name" className="form-label">
            Name
          </label>
          <input
            type="text"
            name="name"
            className="form-control"
            placeholder="John Doe"
            value={formik.values.name}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
          />
          {formik.errors.name && (
            <div className="text-danger">{formik.errors.name}</div>
          )}
        </div>

        <div className="mb-3">
          <label htmlFor="email" className="form-label">
            Email
          </label>
          <input
            type="email"
            name="email"
            className="form-control"
            placeholder="john@example.com"
            value={formik.values.email}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
          />
          {formik.errors.email && (
            <div className="text-danger">{formik.errors.email}</div>
          )}
        </div>

        <div className="mb-3">
          <label htmlFor="message" className="form-label">
            Message
          </label>
          <textarea
            name="message"
            className="form-control"
            placeholder="Your message ..."
            value={formik.values.message}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
          />
          {formik.errors.message && (
            <div className="text-danger">{formik.errors.message}</div>
          )}
        </div>

        <button type="submit" className="btn btn-primary">
          Send
        </button>
      </form>
    </div>
  );
};

export default Home;
```

And voilà. We've just integrated `Formik` to a Next project in Typescript with Boostrap and Yup.
Here's a GIF showing the demo.

![Next JS Form with Formik](https://creativedesignsguru.com/assets/images/themes/next-js-form-formik-contact.png)

## Conclusion

In this article, we've learned how to build a contact form using Formik and Yup with Next and TypeScript.

# React SaaS Boilerplate

[React SaaS Boilerplate](https://nextlessjs.com) is the perfect starter kit to launch your SaaS faster and better. Focus on your business, products and customers instead of losing your time to implement basic functionalities like authentication, recurring payment, landing page, user dashboard, form handling, error handling, CRUD operation, database, etc.

[![Next JS SaaS Boilerplate Starter](https://creativedesignsguru.com/assets/images/themes/nextless-react-saas-boilerplate.png)](https://nextlessjs.com)