React JS Form Validation Using Formik useFormik Hook and Yup Package

Form validation is crucial for client and server-side verification of user information. In this post, I’ll show you how to validation in React JS using package Formik’s useFormik hook and yup schema builder to validate.

In this post, I’ll take an example of a product form validation where fields such as name, price, and image must be validated. Initially, I’ll show you a simple way to validate the fields and next the same example will be used with the yup schema builder package.

Configure jsconfig.file

I’ll be using absolute imports instead of relative imports so need to the modify jsconfig.json file. If you don’t have it then create it in the root folder of your project.

In \jsconfig.json

{
    "compilerOptions": {
        "baseUrl": "src"
    },
    "include": ["src"]
}

Installation of Formik

Use the below command to install formik package.

npm install formik --save

You can verify package installation by going to package.json and the package is added under dependencies “formik”: “^2.2.9”,.

Creating Component

The component src\components\product-form.js is created.

import { useFormik } from 'formik';
import React from 'react'
import './product-form.css';

export default function ProductForm() {
    
    const formik = useFormik({
        initialValues : {
            name : '',
            price : '',
            image : '',
        },
        validate : values => {
            let errors = {}

            if( values.name.length === 0 ){
                errors.name = "This field is required"
            }

            if( values.price.length === 0 ){
                errors.price = "This field is required"
            }

            if( values.image.length === 0 ){
                errors.image = "This is required."
            } else {
                let type = values.image.type.split("/")[0]

                if( type !== "image" ){
                    errors.image = "The Uploaded file must be a Image."
                }
            }

            return errors
        },
        onSubmit: values => {
            console.log(`values`, values)
        }
    })

    return (
        <div className="container" >
            <div className="center" >
                <form onSubmit={formik.handleSubmit} >
                    <div>
                        <label>Product Name</label>
                        <div>
                            <input onChange={formik.handleChange} name="name" type="text" value={formik.values.name} />
                            { formik.errors.name ? <div>{ formik.errors.name }</div> : null }
                        </div>
                    </div>

                    <div>
                        <label>Product Price</label>
                        <div>
                            <input onChange={formik.handleChange} name="price" value={formik.values.price} type="number" step="any" />
                            { formik.errors.price ? <div>{ formik.errors.price }</div> : null }
                        </div>
                    </div>

                    <div>
                        <label>Product Image</label>
                        <div>
                            <input type="file" onChange={ ( e ) => formik.setFieldValue( "image", e.target.files[0] ) } name="image" />
                            { formik.errors.image ? <div>{ formik.errors.image }</div> : null }
                        </div>
                    </div>
                    

                    <div>
                        <input type="submit" className="mt-20" value="Save" />
                    </div>

                </form>
            </div>
        </div>
    )
}
    

Here import useFormik using import { useFormik } from 'formik';. The hook useFormik takes certain parameters mentioned below.

Also check out the documentation of Formik Package

initialValues : The values to be assigned to form fields initially. This is an object that contains the values with the key as a field name.
Example:

            initialValues : {
                name : '',
                price : '',
                image : '',
            },
  • validate : This parameter takes a function and returns an error object. This is called every time a field value changes and the returned objects can be used to display the error message to the user.
    Example

                validate : values => {
                    let errors = {}
    
                    // validation checking
    
                    return errors
                }
    
  • onSubmit : This takes a function and is triggered when a form is submitted.
    Example

                onSubmit: values => {
                    console.log(`values`, values)
                }
    

    The parameter values contains the values assigned to fields. You must pass this method to the form action attribute <form onSubmit={formik.handleSubmit} ></form>

Tips:

If you want to set a custom value to a particular field then use formik.setFieldValue( "field_name", "value" ) the method. You can also do this outside of form within and other methods also.

Styling ProductForm Component

In src\components\product-form.css

.container{
    margin: 0 auto;
}

.container > .center{
    width: 400px;
    margin: auto;
    padding: 25px 0;
}

.container .center > form{
    position: relative;
    left: 50%;
    transform: translateX(-25%);
}

.mt-20{
    margin-top: 20px;
}
    
You can also check out other related posts on Learn to Create a Simple Reusable Tab Component with React JS

Render Component ProductForm

Before running the project, specify ProductForm a component as the entry point or default component of the application.
In src\index.js

import ProductForm from 'components/product-form';

ReactDOM.render(
    <React.StrictMode>
        <ProductForm />
    </React.StrictMode>,
    document.getElementById('root')
);

Output

Product Form validation using Formik's useFormik hook
Product Form validation using Formik’s useFormik hook

Sandbox

Using Yup Schema Object with useFormik Hook for Form Validation

Installation of Yup Package

The Yup is used as a validation rule builder. It takes an object where keys are the field names and the values are the objects. The Yup is a popular package and is mostly used which formik and validation purposes.

npm install -S yup

Create Component ProductYupForm

Previously, I have shown you how to validate form using a simple object. Now I’ll be using the yup object to validate the form and also learn to create a custom validation rule.

In src\components\product-yup-form.js

import { useFormik } from 'formik';
import React from 'react'
import './product-form.css';
import * as yup from 'yup'

export default function ProductYupForm() {

    yup.addMethod( yup.mixed, 'file', function( error_message ) {
        return this.test( 'test-file', error_message, function( value ) {
            return ( value instanceof File )
        } )
    } )

    yup.addMethod( yup.mixed, 'allowedMime', function( mime, error_message=null  ) {
        return this.test( 'test-file-mime', error_message, function( value ) {
            if( !value ){
                return
            }
            let _mime = value.type.split("/")[0]
            let { path, createError } = this
            return (
                _mime === mime ||
                createError( { path, message: ( error_message != null )? error_message : `Only ${mime} type of files are allowed` } )
            )
        } )
    } )

    const formik = useFormik({
        initialValues : {
            name : '',
            price : '',
            image : '',
        },
        validationSchema : yup.object(
            {
                name : yup.string().required("Name required."),
                price : yup.number().min(1).required("Price is required"),
                image : yup.mixed().required("File is required").file( "Must be a file" ).allowedMime("image"),
            }
        ),
        onSubmit: values => {
            console.log(`values`, values)
        }
    })

    return (
        <div className="container" >
            <div className="center" >
                <form onSubmit={formik.handleSubmit} >
                    <div>
                        <label>Product Name</label>
                        <div>
                            <input onChange={formik.handleChange} name="name" type="text" value={formik.values.name} />
                            { formik.errors.name ? <div>{ formik.errors.name }</div> : null }
                        </div>
                    </div>

                    <div>
                        <label>Product Price</label>
                        <div>
                            <input onChange={formik.handleChange} name="price" value={formik.values.price} type="number" step="any" />
                            { formik.errors.price ? <div>{ formik.errors.price }</div> : null }
                        </div>
                    </div>

                    <div>
                        <label>Product Image</label>
                        <div>
                            <input type="file" onChange={ ( e ) => formik.setFieldValue( "image", e.target.files[0] ) } name="image" />
                            { formik.errors.image ? <div>{ formik.errors.image }</div> : null }
                        </div>
                    </div>
                    

                    <div>
                        <input type="submit" className="mt-20" value="Save" />
                    </div>

                </form>
            </div>
        </div>
    )
}
    

In the form the validate must be replaced by validationSchema and the image is an object field that returns an object. And we need to validate whether it is a type that belongs to the class File and also we need to check that the uploaded file belongs to an image type and for this, there is an addMethod available through which you can create custom validation rules.

Also check out documentation of Yup Package

Creating custom validation rule in Yup Package using addMethod

Here we have created two validation rules which are file and allowedMime.

The rule file checks whether the uploaded data is a File.

yup.addMethod( yup.mixed, 'file', function( error_message ) {
    return this.test( 'test-file', error_message, function( value ) {
        return ( value instanceof File )
    } )
} )

The allowedMime check the type of file uploaded.

yup.addMethod( yup.mixed, 'allowedMime', function( mime, error_message=null  ) {
    return this.test( 'test-file-mime', error_message, function( value ) {
        if( !value ){
            return
        }
        let _mime = value.type.split("/")[0]
        let { path, createError } = this
        return (
            _mime === mime ||
            createError( { path, message: ( error_message != null )? error_message : `Only ${mime} type of files are allowed` } )
        )
    } )
} )

The yup.addMethod(...) returns a test function which is executed by formik validationSchema.

Render Component ProductYupForm

In src\index.js

import ProductYupForm from './components/product-yup-form';

ReactDOM.render(
  <React.StrictMode>
    <ProductYupForm />
  </React.StrictMode>,
  document.getElementById('root')
);

Watch Video

Conclusion

Thank you for reading and here is the link to the Github repository.

Summary
Review Date
Reviewed Item
React JS Form Validation Using Formik useFormik Hook and Yup Package
Author Rating
51star1star1star1star1star
Software Name
React JS
Software Name
Windows Os, Mac Os, Ubuntu Os
Software Category
Web Development