React Form Validation example with Formik and Yup

In this tutorial, I will show you how to implement React Form Validation and Submit example using Formik, Yup and Bootstrap 4.

More Practice:
React.js CRUD example with Rest API
React File Upload with Axios and Progress Bar to Rest API
React JWT Authentication (without Redux) example
React Redux: JWT Authentication example

Serverless:
React Firebase CRUD with Realtime Database
React Firestore CRUD App example | Firebase Cloud Firestore


Using Hooks instead:
React Form Validation example with Hooks, Formik and Yup

Overview of React Form Validation example

We will implement validation for a React Form using Formik and Bootstrap 4. The form has:

  • Full Name: required
  • Username: required, from 6 to 20 characters
  • Email: required, email format
  • Password: required, from 6 to 40 characters
  • Confirm Password: required, same as Password
  • Accept Terms Checkbox: required

react-form-validation-example-formik-yup

Some fields could be wrong:

react-form-validation-example-formik-yup-submit-error

Successful Submission will look like this:

react-form-validation-example-formik-yup-submit

Technology

We’re gonna use following modules:

  • react 17/16
  • bootstrap 4
  • formik 2
  • yup

Setup Project

First we need to install necessary modules.
Open your project root folder, run the command:

npm install formik yup

# Or:
yarn add formik yup

Open package.json, the dependencies will look like this:

{
  "name": "react-form-validation-example",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    ...
    "formik": "^2.2.9",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "yup": "^0.32.9"
  },
  ...
}

Import Bootstrap

Open public/index.html and add following line to <head> tag:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <link href="//netdna.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
    ...
    <title>React Form Validation example</title>
  </head>
  <body>
    ...
    <div id="root"></div>
  </body>
</html>

Or you can run command: npm install bootstrap.

Then open src/App.js and modify the code inside it as following-

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";

function App() {
  return (
    ...
  );
}

export default App;

React Form Validation example with Formik

The app component contains Form Validation example built with Formik and Yup library.

Formik, together with Yup, help handling forms conveniently in React. With Yup, we can create schema for validation abstractly instead of creating custom validation for each input field.

You need to notice following important Formik attributes:

  • initialValues
  • validationSchema
  • onSubmit

Open src/App.js, we’re gonna import necessary library first:

import React from 'react';
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';

Next we use Yup schema validation library for Form validation rules:

class App extends React.Component {
  ...

  validationSchema() {
    return Yup.object().shape({
      fullname: Yup.string().required('Fullname is required'),
      username: Yup.string()
        .required('Username is required')
        .min(6, 'Username must be at least 6 characters')
        .max(20, 'Username must not exceed 20 characters'),
      email: Yup.string()
        .required('Email is required')
        .email('Email is invalid'),
      password: Yup.string()
        .required('Password is required')
        .min(6, 'Password must be at least 6 characters')
        .max(40, 'Password must not exceed 40 characters'),
      confirmPassword: Yup.string()
        .required('Confirm Password is required')
        .oneOf([Yup.ref('password'), null], 'Confirm Password does not match'),
      acceptTerms: Yup.bool().oneOf([true], 'Accept Terms is required'),
    });
  }
  ...
}

When the form is valid and submitted, handleSubmit() method is called and the form data will show in console:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  ...

  handleSubmit(data) {
    console.log(JSON.stringify(data, null, 2));
  }
  ...
}

React Form Validation with Formik template

Now we create the form with input fields and validation messages.

class App extends React.Component {
  ...

  render() {
    const initialValues = {
      fullname: '',
      username: '',
      email: '',
      password: '',
      confirmPassword: '',
      acceptTerms: false,
    };

    return (
      <div className="register-form">
        <Formik
          initialValues={initialValues}
          validationSchema={this.validationSchema}
          onSubmit={this.handleSubmit}
        >
          {({ errors, touched, resetForm }) => (
            <Form>
              <div className="form-group">
                <label>Full Name</label>
                <Field
                  name="fullname"
                  type="text"
                  className={
                    'form-control' +
                    (errors.fullname && touched.fullname ? ' is-invalid' : '')
                  }
                />
                <ErrorMessage
                  name="fullname"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group">
                <label htmlFor="username"> Username </label>
                <Field
                  name="username"
                  type="text"
                  className={
                    'form-control' +
                    (errors.username && touched.username ? ' is-invalid' : '')
                  }
                />
                <ErrorMessage
                  name="username"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group">
                <label htmlFor="email"> Email </label>
                <Field
                  name="email"
                  type="email"
                  className={
                    'form-control' +
                    (errors.email && touched.email ? ' is-invalid' : '')
                  }
                />
                <ErrorMessage
                  name="email"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group">
                <label htmlFor="password"> Password </label>
                <Field
                  name="password"
                  type="password"
                  className={
                    'form-control' +
                    (errors.password && touched.password ? ' is-invalid' : '')
                  }
                />
                <ErrorMessage
                  name="password"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group">
                <label htmlFor="confirmPassword"> Confirm Password </label>
                <Field
                  name="confirmPassword"
                  type="password"
                  className={
                    'form-control' +
                    (errors.confirmPassword && touched.confirmPassword
                      ? ' is-invalid'
                      : '')
                  }
                />
                <ErrorMessage
                  name="confirmPassword"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group form-check">
                <Field
                  name="acceptTerms"
                  type="checkbox"
                  className={
                    'form-check-input' +
                    (errors.acceptTerms && touched.acceptTerms
                      ? ' is-invalid'
                      : '')
                  }
                />
                <label htmlFor="acceptTerms" className="form-check-label">
                  I have read and agree to the Terms
                </label>
                <ErrorMessage
                  name="acceptTerms"
                  component="div"
                  className="invalid-feedback"
                />
              </div>

              <div className="form-group">
                <button type="submit" className="btn btn-primary">
                  Register
                </button>
                <button
                  type="button"
                  onClick={resetForm}
                  className="btn btn-warning float-right"
                >
                  Reset
                </button>
              </div>
            </Form>
          )}
        </Formik>
      </div>
    );
  }
}

export default App;

initialValues: object for initial values of the form fields. Each key of the object must correspond with the name of the Formik input field.

validationSchema: function for handling validation. It receives form data values and validates each property based on the rules defined. Each key of the object must correspond with the name of the Formik input field.

onSubmit: function for handling submission. It receives callback function that will run when the validation has passed without any error.

Form: wraps the HTML <form> element.

Field: links the form input’s onChange, onBlur and value attributes to Formik’s handleChange, handleBlur, and values object. It uses the name attribute to match up with Formik state.

We can decide the HTML element to render using as.
For example:
<Field as="textarea" name="color">
or: <Field as="select" name="color">.

By default, it renders HTML input field.

ErrorMessage: handles the error message based on the name attribute corresponding to the Field‘s name. By default, it renders a string if the component attribute is not specified.

Run React Form Validation example

You can run our App with command: yarn start or npm run start.
If the process is successful, open Browser with Url: http://localhost:3000/ and check it.

Or run on Stackblitz:

Conclusion

Today we’ve built a React Form Validation example successfully with Formik, Yup & Bootstrap 4.

You can also use the Form Validation in following posts:
React.js CRUD example with Rest API
React JWT Authentication (without Redux) example
React Redux: JWT Authentication example

Or using Hooks instead:
React Form Validation example with Hooks, Formik and Yup

Further Reading

React File Upload with Axios and Progress Bar to Rest API
React Pagination with API using Material-UI

Serverless with Firebase:
React Firebase CRUD with Realtime Database
React Firestore CRUD App example | Firebase Cloud Firestore

Fullstack:
React + Spring Boot + MySQL: CRUD example
React + Spring Boot + PostgreSQL: CRUD example
React + Spring Boot + MongoDB: CRUD example
React + Node.js + Express + MySQL: CRUD example
React + Node.js + Express + PostgreSQL example
React Redux + Node.js + Express + MySQL: CRUD example
React + Node.js + Express + MongoDB example
React + Django example

3 thoughts to “React Form Validation example with Formik and Yup”

Comments are closed to reduce spam. If you have any question, please send me an email.