DEV Community

Cover image for Next.JS - Kick-Ass Form Handling Using React-Hook-Form, Yup and Bootstrap
Jay @ Designly
Jay @ Designly

Posted on • Updated on • Originally published at blog.designly.biz

Next.JS - Kick-Ass Form Handling Using React-Hook-Form, Yup and Bootstrap

If there's one thing in front-end development that I hate the most, that would be forms. Forms are the worst! Form validation is a very important part of gathering user data as we want to make sure we get the data in the format we expect. Otherwise, bad things often happen!

I chose Next.JS as our framework for this demo because I use it for just about everything. Next.JS is a layer on top of ReactJS, a full-stack framework created by Facebook that uses Javascript for both front- and back-end code.

This tutorial will be a two-part series. The first will deal with the front end development. The second will deal with the back-end.

We will be using the following libraries for this project:

Package Name Description
React-Bootstrap The most popular front-end framework created by Twitter
React-Hook-Form Performant, flexible and extensible forms with easy-to-use validation
Yup A schema builder for runtime value parsing and validation

Step 1 - Create a Next.JS Project

First let's initialize a new basic Next.JS project using create-next-app.

npx create-next-app@latest your-project-name
Enter fullscreen mode Exit fullscreen mode

Now let's install our dependencies:

cd your-project-name
npm install @hookform/resolvers react-hook-form yup react-bootstrap bootstrap sass
Enter fullscreen mode Exit fullscreen mode

Step 2 - Define Our Styles

Delete the default styles in /styles and create a file called App.scss:

@import "~bootstrap/scss/bootstrap";

.navbar {
    padding: 1em;
    margin-bottom: 1em;

    &-brand {
        color: white;
        cursor: pointer;
        &:hover {
            color: yellow;
        }
    }

    a {
        color: white;
        text-decoration: none;
        &:hover {
            color: rgb(124, 124, 232);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now in /pages/_app.js, modify it to look like this:

import '../styles/App.scss';

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp
Enter fullscreen mode Exit fullscreen mode

If you're unfamiliar with SASS, I highly recommend you study up and begin using it. Check out this tutorial.

Step 3 - Create Our Form

Let's modify the default /pages/index.js for our example to look like this:

import React from 'react';
import Link from 'next/link';
import { Col, Container, Row, Navbar, Form, Button } from 'react-bootstrap';
import { useForm } from 'react-hook-form';
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";

export default function Home() {
  // Yup error message overrides
  const errMess = {
    req: "Please fill this out"
  };

  // Our Yup Schema for this form
  const ContactSchema = yup.object().shape({
    name: yup.string()
      .label('Full Name')
      .required(errMess.req)
      .min(3)
      .max(20),
    email: yup.string()
      .label('Email Address')
      .required(errMess.req)
      .email('Invalid Email Address'),
    message: yup.string()
      .label('Message')
      .required(errMess.req)
      .min(10)
      .max(1000),
  });

  // Destruct useForm() and set our Yup schema as the validation resolver
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(ContactSchema)
  });

  // Our function for handling valid form data
  const submitForm = (data) => {
    alert(JSON.stringify(data));
  }

  return (
    <>
      <Navbar bg="dark" expand="lg">
        <Navbar.Brand>
          <Link href="/">
            Home
          </Link>
        </Navbar.Brand>
      </Navbar>
      <Container>
        <h1 className='mb-5'>Next.JS Form to Email Example</h1>
        <Form onSubmit={handleSubmit((data) => submitForm(data))}>
          <Row>
            <Col>
              <Form.Group className="mb-3" controlId="nameField">
                <Form.Label>Full Name</Form.Label>
                <Form.Control
                  type="text"
                  placeholder="e.g. John Doe"
                  isInvalid={errors.name}
                  {...register('name')}
                />
                <Form.Control.Feedback type='invalid'>
                  {errors.name?.message}
                </Form.Control.Feedback>
              </Form.Group>
            </Col>
            <Col>
              <Form.Group className="mb-3" controlId="emailField">
                <Form.Label>Email Address</Form.Label>
                <Form.Control
                  type="email"
                  placeholder="e.g. john@example.com"
                  isInvalid={errors.email}
                  {...register('email')}
                />
                <Form.Control.Feedback type='invalid'>
                  {errors.email?.message}
                </Form.Control.Feedback>
              </Form.Group>
            </Col>
            <Col lg={12}>
              <Form.Group className="mb-3" controlId="messageField">
                <Form.Label>Message</Form.Label>
                <Form.Control
                  as="textarea"
                  rows={5}
                  placeholder="Please type your message..."
                  isInvalid={errors.message}
                  {...register('message')}
                />
                <Form.Control.Feedback type='invalid'>
                  {errors.message?.message}
                </Form.Control.Feedback>
              </Form.Group>
            </Col>
          </Row>
          <Row>
            <Col>
              <Button variant="primary" type="submit">
                Submit
              </Button>
            </Col>
          </Row>
        </Form>

      </Container>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now run npm run dev and navigate to http://localhost:3000 to test our form. Should get something like this:

End Result

That's it. It's so easy! Yup in conjunction with React-Hook-Form makes creating forms with validation a breeze! Don't forget, though, you always want to validate on the back-end as well.

If you want the full code base for this project, you can clone my repository here.

If you'd like to proceed to the next tutorial on how to handle the back-end, check out my next article: Simple Next.JS Form to Email Using React-Hook-Form and Gmail.

Top comments (0)