Introduction
Creating user-friendly forms is a crucial aspect of web development, but it can be challenging. Recently, I contributed to an open-source project where I built a registration form for a web application using React, Formik, and Yup. Through this experience, I gained valuable insights into creating a great user experience while implementing a robust form validation system.
In this blog post, I'll share what I learned and provide a simple guide on how to use Formik and Yup for form validation in React applications. If you are just starting, this guide will provide you with the necessary tools to create an effective form using these libraries.
Prerequisites
Basic understanding of React: You have a basic understanding of React (or at least have built or worked with React components). However, you can still follow along and learn if you're new to React or any of the technologies used in this article.
Familiarity with JavaScript: You have a solid understanding of JavaScript and its fundamental concepts, including variables, functions, and objects.
Familiarity with HTML and CSS: You should be familiar with HTML and CSS to create and style the form.
A code editor (VS Code is recommended) and, of course, a web browser
What are Formik and Yup?
Formik is a popular library for building forms in React. It simplifies form management by handling form state, validation, and submission, and provides a clean API for rendering and updating form fields. Yup is a schema validation library that works well with Formik, allowing us to define the validation rules for our form fields.
Part 1: Setting Up the Registration Form
To start with, we need to set up the basic structure of our registration form. We'll create a new component called RegistrationForm, which will contain all the form fields and validation logic. The first step is to install Formik and Yup by running the following command in your terminal:
npm install formik yup
Next, let's import Formik and Yup into our component:
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
Let's create our RegistrationForm
component. We will use the Formik component to wrap the Form component, both of which have been imported from formik
and it takes three props:
initialValues: an object containing the initial values of our form fields
validation schema: a Yup schema that defines the validation rules for our form fields
onSubmit: a function that's called when the form is submitted.
And then we have the
isSubmitting
boolean property destructed from the Formik component's render props, and it is set to true during form submission or false when the process is completed. We will use this property to disable the submit button once we trigger the form submission process. You can also use it to display a loading spinner.Using this property gives a great user experience as it lets the user know when a submission process is in progress.
const RegistrationForm = () => {
return (
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
eventType: '',
password: '',
confirmPassword: ''
}}
validationSchema={/* add Yup validation schema here */}
onSubmit={/* add form submission logic here */}
>
{({ isSubmitting }) => (
<Form>
{/* add form fields here */}
<button type="submit" disabled={isSubmitting}>
Sign Up
</button>
</Form>
)}
</Formik>
);
};
Part 2: Adding Form Fields
Now that we have our basic component, let's add the form fields. We'll use Formik'sField component
to create each form field. Each form field takes a name prop that matches the corresponding key in our initialValues
object.
// Renders an HTML <input> by default
<Field name="firstName" placeholder="First Name" />
<Field name="lastName" placeholder="Last Name" />
<Field name="email" placeholder="Email" />
// Renders an HTML <select>
<Field name="eventType" as="select">
<option value="virtual">Virtual</option>
<option value="inPerson">In-person</option>
</Field>
<Field name="password" type="password" placeholder="Password" />
<Field name="confirmPassword" type="password" placeholder="Confirm Password" />
Then, let's use theErrorMessage
component, which also takes a name prop, and/or component prop (optional) from Formik, to display validation errors next to each form field.
<Field name="firstName" placeholder="First Name" />
<ErrorMessage name="firstName" component="div" />
Part 3: Adding Form Validation
After setting up our form fields, we can add validation to our form. We'll use Yup to define the validation schema for our form. In this case, we want to ensure that all fields are required and that the email and password fields meet specific criteria. Here's the validation schema for our fields: You can check out the Yup docs for more details on defining your schema.
const validationSchema = Yup.object().shape({
firstName: Yup.string().required('First name is required'),
lastName: Yup.string().required('Last name is required'),
email: Yup.string().email('Invalid email').required('Email is required'),
eventType: Yup.string().required('Event type is required'),
password: Yup.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters long'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match')
.required('Confirm Password is required')
});
We'll then pass this validation schema to the Formik
component as a prop.
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
eventType: '',
password: '',
confirmPassword: ''
}}
validationSchema={validationSchema}
onSubmit={/* add form submission logic here */}
>
Part 4: Handling Form Submission
We have our form fields and validation set up; now we need to handle the form submission. We'll use theonSubmit
prop in the Formik component to define what happens when the user submits the form.
setSubmitting
What this function does is set theisSubmitting
property to either true or false, depending on the boolean it is called with. If it is called with the booleantrue,
theisSubmitting
sets totrue
, and if it is called withfalse
,isSubmitting
sets tofalse
.resetForm
It is a function provided by Formik that resets the form to its original initial values. By using theresetForm
method, we can easily reset the form to its initial state after submission, making it easier for the user to fill out the form multiple times without having to clear the fields manually.
const handleSubmit = (values, { setSubmitting, resetForm }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
}, 400);
};
We'll pass this function to the onSubmit
prop in our RegistrationForm component:
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
eventType: '',
password: '',
confirmPassword: ''
}}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
Part 5: Putting It All Together
With all the pieces in place, let's see our form component in action:
const RegistrationForm = () => {
const validationSchema = Yup.object().shape({
firstName: Yup.string().required('First name is required'),
lastName: Yup.string().required('Last name is required'),
email: Yup.string().email('Invalid email').required('Email is required'),
eventType: Yup.string().required('Event type is required'),
password: Yup.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters long'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match')
.required('Confirm Password is required')
});
const handleSubmit = (values, { setSubmitting, resetForm }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
}, 400);
};
return (
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
eventType: '',
password: '',
confirmPassword: ''
}}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({ isSubmitting }) => (
<Form>
<Field name="firstName" placeholder="First Name" />
<ErrorMessage name="firstName" />
<Field name="lastName" placeholder="Last Name" />
<ErrorMessage name="lastName" />
<Field name="email" placeholder="Email" />
<ErrorMessage name="email" />
<Field name="eventType" as="select">
<option value="virtual">Virtual</option>
<option value="inPerson">In-person</option>
</Field>
<ErrorMessage name="eventType" />
<Field name="password" type="password" placeholder="Password" />
<ErrorMessage name="password" />
<Field name="confirmPassword" type="password" placeholder="Confirm Password" />
<ErrorMessage name="confirmPassword" />
<button type="submit" disabled={isSubmitting}>
Sign Up
</button>
</Form>
)}
</Formik>
);
};
Conclusion
Great! You have just learned how to add validations to your form using Yup, set up the form fields, and handle the form submission with Formik. This blog post is mostly focused on form validation and submission, so we didn't cover the handleChange
method that is usually called with the onChange
prop in your form fields. With Formik and Yup, building robust and user-friendly forms in React is a breeze. I hope this tutorial has helped get started with building your own validated forms in React!
Kindly drop any suggestions or corrections in the comment section.