April 10 2019

React + Formik - Form Validation Example

Example built with React 16.8.6 and Formik 1.5.2

Other versions available:

This is a quick example of how to setup form validation in React with the Formik library. Formik contains a higher order component that helps with managing react state, validation, error messages and form submission. Validation is done with the Yup object schema validator which hooks into Formik via the handy validationSchema prop.

The example is a simple registration form with pretty standard fields for first name, last name, email, password and confirm password. All fields are required, the email field must be a valid email address, the password field must have a min length of 6 and must match the confirm password field.

Styling of the React + Formik example is all done with Bootstrap 4 CSS.

Here it is in action: (See on StackBlitz at https://stackblitz.com/edit/react-formik-form-validation)

React + Formik Form Validation App Component

The app component contains an example registration form built with the <Formik /> component. The initial values of each field are set in the initialValues property. Validation rules and error messages are set in the validationSchema property. The onSubmit property contains a function that gets called when the form is submitted and valid. The html and jsx markup for the form is set in the render property.

The <Field /> and <ErrorMessage /> components are part of the Formik library that automatically hook up inputs and error messages with the fields defined in Formik. For more info about the helper components available check out the Formik docs.

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

class App extends React.Component {
    render() {
        return (
                    firstName: '',
                    lastName: '',
                    email: '',
                    password: '',
                    confirmPassword: ''
                    firstName: Yup.string()
                        .required('First Name is required'),
                    lastName: Yup.string()
                        .required('Last Name is required'),
                    email: Yup.string()
                        .email('Email is invalid')
                        .required('Email is required'),
                    password: Yup.string()
                        .min(6, 'Password must be at least 6 characters')
                        .required('Password is required'),
                    confirmPassword:  Yup.string()
                        .oneOf([Yup.ref('password'), null], 'Passwords must match')
                        .required('Confirm Password is required')
                onSubmit={fields => {
                    alert('SUCCESS!! :-)\n\n' + JSON.stringify(fields, null, 4))
                render={({ errors, status, touched }) => (
                        <div className="form-group">
                            <label htmlFor="firstName">First Name</label>
                            <Field name="firstName" type="text" className={'form-control' + (errors.firstName && touched.firstName ? ' is-invalid' : '')} />
                            <ErrorMessage name="firstName" component="div" className="invalid-feedback" />
                        <div className="form-group">
                            <label htmlFor="lastName">Last Name</label>
                            <Field name="lastName" type="text" className={'form-control' + (errors.lastName && touched.lastName ? ' is-invalid' : '')} />
                            <ErrorMessage name="lastName" component="div" className="invalid-feedback" />
                        <div className="form-group">
                            <label htmlFor="email">Email</label>
                            <Field name="email" type="text" className={'form-control' + (errors.email && touched.email ? ' is-invalid' : '')} />
                            <ErrorMessage name="email" component="div" className="invalid-feedback" />
                        <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 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 className="form-group">
                            <button type="submit" className="btn btn-primary mr-2">Register</button>
                            <button type="reset" className="btn btn-secondary">Reset</button>

export { App }; 

React + Formik Form Validation Index HTML File

The base index html file contains the outer html for the whole tutorial application.

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <title>React + Formik - Form Validation Example</title>

    <!-- bootstrap css -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" />

        a { cursor: pointer; }
    <div class="jumbotron">
        <div class="container">
            <div class="row">
                <div class="col-md-6 offset-md-3">
                    <h3>React + Formik - Form Validation</h3>
                    <div id="app"></div>

React + Formik Form Validation Main Entry File

The root index.jsx file bootstraps the react tutorial application by rendering the App component into the #app div element defined in the base index html file above.

import React from 'react';
import { render } from 'react-dom';

import { App } from './App';

    <App />,


Web Development Sydney

Feel free to contact me if you're looking for a web developer in Sydney, I also provide remote contracting services for clients outside Sydney.