Build Robust and User-Friendly Forms by using Formik and Validate using Yup in ReactJS

Rahul Kumar
6 min readMar 28, 2024

--

Q1. what are the popular 3rd Party for Forms in React?

  • Formik [ Popular ]
  • KendoForms
  • React-Hook-Forms [Trending after React 16+ version]
  • React-Final-Forms etc.

In this blog, we will setup formik and yup library for form and validating the form.

Let’s get stated with Formik:

Note: In this blog, I have used bootstrap for styling

Step 1. Install Formik library for your project.

$ npm install formik --save

Step 2. Import useFormik hook

import {useFormik} from 'formik';

Step 3. Configure formik form with values and submit event.

const formik = useFormik({
initialValues: {},
onSubmit: function(){},
})
  • initialValues is an Object that defines the values to use for form.
  • onSubmit defines the actions to perform on form submit.

Step 4. Binding the formik values and events to form elements

<form onSubmit={formik.handleSubmit}>
<input
type='text
name='username'
value={formik.values.UserName}
onChange={formik.handleChange}
/>
</form>

Step 5. Accessing the form data and using into component:

<dd>{formik.values.UserName} </dd>
const formik = useFormik({
initialValues: {}.
onSubmit: function(values){
alert(JSON.stringify(values);
},
})

Example:

Example 1. Simple Code

import { Formik, useFormik } from "formik";
import React from "react";
const FormikDemo = () => {
const formik = useFormik({
initialValues: {
username: "",
password: "",
city: "",
},
onSubmit: (values) => {
alert(JSON.stringify(values));
},
});
return (
<div className="container fluid">
<form onSubmit={formik.handleSubmit}>
<h2>Register User</h2>
<dl>
<dt>User Name:</dt>
<dd>
<input
type="text"
name="username"
value={formik.values.username}
onChange={formik.handleChange}
required
/>
</dd>
<dt>Password: </dt>
<dd>
<input
type="password"
name="password"
value={formik.values.password}
onChange={formik.handleChange}
required
/>
</dd>
<dt>Select the City:</dt>
<dd>
<select
name="city"
value={formik.values.city}
onChange={formik.handleChange}
required
>
<option value="">---Select City---</option>
<option value="bangalore">Bangalore</option>
<option value="delhi">Delhi</option>
<option value="mumbai">Mumbai</option>
<option value="chennai">Chennai</option>
</select>
</dd>
</dl>
<button className="btn btn-primary" >Submit</button>
</form>
{/* <dd>{JSON.stringify(formik.values)}</dd> */}
</div>
);
};
export default FormikDemo;

Example 2. With boolean values:

import { Formik, useFormik } from "formik";
import React from "react";
const FormikDemo = () => {
const formik = useFormik({
initialValues: {
username: "",
password: "",
city: "",
subscribed: false,
},
onSubmit: (values) => {
alert(`Name: ${values.username}\n Subscribed: ${values.subscribed ? " subscribed" : "Not subscribed"}`);
},
});
return (
<div className="container fluid">
<form onSubmit={formik.handleSubmit}>
<h2>Register User</h2>
<dl>
<dt>User Name:</dt>
<dd>
<input
type="text"
name="username"
value={formik.values.username}
onChange={formik.handleChange}
required
/>
</dd>
<dt>Password: </dt>
<dd>
<input
type="password"
name="password"
value={formik.values.password}
onChange={formik.handleChange}
required
/>
</dd>
<dt>Select the City:</dt>
<dd>
<select
name="city"
value={formik.values.city}
onChange={formik.handleChange}
required
>
<option value="">---Select City---</option>
<option value="bangalore">Bangalore</option>
<option value="delhi">Delhi</option>
<option value="mumbai">Mumbai</option>
<option value="chennai">Chennai</option>
</select>
</dd>
<dt>Subscribe</dt>
<dd className="form-check form-switch">
<input className="form-check-input" type="checkbox" name="subscribed" checked={formik.values.subscribed} onChange={formik.handleChange} />
</dd>
</dl>
<button className="btn btn-primary">Submit</button>
</form>
{/* <dd>{JSON.stringify(formik.values)}</dd> */}
</div>
);
};
export default FormikDemo;

How to handle the validations using Formik:

  • Validation is the process of verifying user input.
  • Validation is required to ensure that contradictionary and unauthorized data is not get stored into the database.
  • React can handle validations without help of third party by using javascript functions. [ It is lenghty process. ]

isNaN(): to verify number or not.

indexOf()

typeOf etc.

We have to use javascript things to validations.

  • React have to use various events to verify the value

onBlur

onKeyUp

onFocus

onChange etc.

  • You configure validation for every element in page by using validation function.
  • Formik can use Validation, form validation function that returns errors object.
  • Here too, you have to javascript methods for verifying the value.

Step 1. Create a function for accepting form values, verfying the values and reporting errors.

function validateForm(values){
const errors = {};
if(values.Name == '') {errors.Name = 'required'}
if(values.Email == '') {errors.Email='required'}
}

useFormik({
initialValues: {},
validation: ValidateForm
})
  • You can access error message by using
{formik.errors.Name}

Example 1: Single condition Validation

import React from "react";
import { useFormik } from "formik";

const FormikValidation = () => {
const formik = useFormik({
initialValues: {
username: "",
age: "",
email: "",
},
onSubmit: (values) => {
alert(`Name: ${values.username}\n age: ${values.age}`);
},
validate: (values) => {
let errors = {};
if (!values.username) {
errors.username = "Required";
}
if (!values.age) {
errors.age = "Required";
}
if (!values.email) {
errors.email = "Required";
}
return errors;
}
});
return (
<div className="container-fluid">
<h2>Register</h2>
<form onSubmit={formik.handleSubmit}>
<dl>
<dt>User Name:</dt>
<dd>
<input
type="text"
name="username"
placeholder="User Name"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.username}</dd>
<dt>Age:</dt>
<dd>
<input
type="text"
name="age"
placeholder="age"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.age}</dd>
<dt>Email:</dt>
<dd>
<input
type="email"
name="email"
placeholder="email"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.email}</dd>

</dl>
<button className="btn btn-primary" >Register</button>
</form>
</div>
);
};
export default FormikValidation;

Example 2: Multiple validations

import React from "react";
import { useFormik } from "formik";

const FormikValidation = () => {
const formik = useFormik({
initialValues: {
username: "",
age: "",
email: "",
mobile: "",
},
validate: (values) => {
let errors = {};
// Validation for username
if (!values.username) {
errors.username = "Required";
} else if (values.username.length > 10) {
errors.username = "Must be less than 10 characters";
} else if (values.username.length < 4) {
errors.username = "Must be more than 4 characters";
}
// Validation for age
if (!values.age) {
errors.age = "Required";
} else if (isNaN(values.age)) {
errors.age = "Must be a number";
}
// Validation for email (Improved)
if (!values.email) {
errors.email = "Required";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) {
errors.email = "Invalid email format";
}
// Validation for mobile number
if (!values.mobile) {
errors.mobile = "Required";
} else if (!values.mobile.match(/\+91\d{10}/)) {
errors.mobile =
"Invalid mobile number (Must start with +91 and be 10 digits)";
} // No need to set errors.mobile to "" here
return errors;
},
onSubmit: (values) => {
alert(`Name: ${values.username}\n age: ${values.age}`);
},
});
return (
<div className="container-fluid">
<h2>Register</h2>
<form onSubmit={formik.handleSubmit}>
<dl>
<dt>User Name:</dt>
<dd>
<input
type="text"
name="username"
placeholder="User Name"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.username}</dd>
<dt>Age:</dt>
<dd>
<input
type="text"
name="age"
placeholder="age"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.age}</dd>
<dt>Email:</dt>
<dd>
<input
type="email"
name="email"
placeholder="email"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.email}</dd>
<dt>Mobile :</dt>
<dd>
<input
type="text"
name="mobile"
placeholder="mobile number"
onChange={formik.handleChange}
/>
</dd>
<dd className="text-danger">{formik.errors.mobile}</dd>
</dl>
<button className="btn btn-primary">Register</button>
</form>
</div>
);
};
export default FormikValidation;

Let’s Validate using Yup Library:

Validation Using YUP Library:

  • It simplifies the form and its validation.
  • Yup library provides validation schemas.
  • Every validation schema[Structure] defines the type and range of value.
  • Validation Schema is Data Structure.
  • Like previously, you need not to explicitly any function to verify the data type or range using javaScript functions.

Yup library provides schemas for validations, for example:

  1. BooleanSchema
  2. NumberSchema
  3. StringSchema

there are many like this…

Yup provides functions for verifying range and pattern.

  1. min()
  2. max()
  3. maxLength()
  4. minlength()
  5. required()
  6. pattern()
  7. email() etc.

Step 1. Install Yup library for Project:

$ npm install yup --save

Step 2. Import Validation schemas in Component:

import * as yup from 'yup';

Step 3. Formik can use Yup validation schema by using “validationSchema” property.

const formik = useFormik({
initialValues: {},
validationSchema: yup.object({
FieldName: yup.DataType().required().min(4).max(10),
})
})

Step 4. Binding the fields with HTML elements.

<input type="text" {...formik.getFieldProps("Name")}/>

We need to configure errors, Internally It will managed yup library.

<dd>{formik.errors.name}</dd>

Example:

Yup validation:

import { useFormik } from "formik";
import React from "react";
import * as yup from "yup";

const YupValidation = () => {
const formik = useFormik({
initialValues: {
username:'',
password: '',
email:'',
},
validationSchema: yup.object({
username: yup.string()
.required('Username is required')
.min(5, 'Username must be at least 5 characters long')
.max(15, 'username must be at max 15 characters long'),
password: yup.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters long'),
email: yup.string()
.required('Email is required')
.email('Invalid Email!'),
}),
onSubmit: (values) => {
alert(JSON.stringify(values));
},
});
return (
<div className="container-fluid w-25">
<h2>Register</h2>
<form onSubmit={formik.handleSubmit}>
<div className="form-group">
<label htmlFor="name">User Name:</label>
<input type="text" className="form-control" id="name" {...formik.getFieldProps('username')}/>
</div>
<p className="text-danger">{formik.errors.username}</p>
<div className="form-group">
<label htmlFor="email">Email</label>
<input type="email" className="form-control" id="email" {...formik.getFieldProps('email')}/>
</div>
<p className="text-danger">{formik.errors.email}</p>
<div className="form-group">
<label htmlFor="password">Password</label>
<input type="password" className="form-control" id="password" {...formik.getFieldProps('password')}/>
</div>
<p className="text-danger">{formik.errors.password}</p>
<br />
<button type="submit" className="btn btn-primary">
Register
</button>
</form>
</div>
);
};
export default YupValidation;

Output:

Thanks…

--

--

Rahul Kumar
Rahul Kumar

Written by Rahul Kumar

MERN Stack Developer building scalable web apps with MongoDB, Express.js, React, and Node.js. Sharing insights and best practices for modern web development.