As covered in the previous article, we can validate forms using controlled components. But it may be time-consuming and the length of the code may increase if we need forms at many places on our website. Here comes Formik and Yup to the rescue! Formik is designed to manage forms with complex validation with ease. Formik supports synchronous and asynchronous form-level and field-level validation. Furthermore, it comes with baked-in support for schema-based form-level validation through Yup. We would also use Bootstrap so that we won’t waste our time on HTML and CSS.
Below is the step-by-step implementation on how to so Form Validation using Formik and Yup.
Step 1: Creating React Application And Installing Module:
npx create-react-app react-form
Step 2: After creating your project folder i.e.react-form, move to it using the following command:
cd react-form
Step 3: Then add Bootstrap (this is optional if you want you can create your own styling).
yarn add bootstrap
Step 4: We can proceed to add Formik and Yup.
yarn add formik yup
Project Structure: It will look like the following.
Note: We will write down the entire code in the App.js file. Here, the App is our default component where we have written our code.
Step 5: <Formik> is a component that helps you with building forms. InitialValues is a prop that initializes all fields in your form. Generally, the initialization is an empty string but in some fields, you may require an initial value.
Javascript
<Formik initialValues={{ email: "" , password: "" }} > |
Step 6: We are adding a code block in which we are passing props provided by Formik and we are printing the props object on the console. Then we use the <Form> Component provided by Bootstrap in which we again pass 2 components namely <label> and <Field> Component. Lastly, we use the Bootstrap <Button> Component for submitting the form. Basic boiler code of form component which should be wrapped inside formik.
Javascript
import React from "react" ; import { Formik, Form, Field } from "formik" ; import "bootstrap/dist/css/bootstrap.css" ; class App extends React.Component { render() { return ( <div className= "container" > <div className= "row" > <div className= "col-lg-12" > <Formik initialValues={{ email: "" , password: "" }}> {(props) => ( <div> {console.log(props)} <div className= "row mb-5" > <div className= "col-lg-12 text-center" > <h1 className= "mt-5" >Login Form</h1> </div> </div> <Form> <div className= "form-group" > <label htmlFor= "email" >Email</label> <Field type= "email" name= "email" placeholder= "Enter email" autoComplete= "off" /> </div> <div className= "form-group" > <label htmlFor= "password" className= "mt-3" > Password </label> <Field type= "password" name= "password" placeholder= "Enter password" /> </div> <button type= "submit" className= "btn btn-primary btn-block mt-4" > Submit </button> </Form> </div> )} </Formik> </div> </div> </div> ); } } export default App; |
Step 7: As discussed, we added a function that takes an argument (let’s say props) and we wrapped our form inside the formik component then we printed the props argument so that we can see various props provided by formik. In the console, an object is displayed. If we look closely we can see that initial values also get displayed in this object.
Step 8: Another prop for Formik is onSubmit which takes values as a parameter and it is mostly used for post api calls to collect the data out of the form and then we can store the data in the server. But in our case, we would keep it simple and just print the values in the console and alert a message.
Javascript
<Formik initialValues={{ email: "" , password: "" }} onSubmit={(values) => { console.log(values) alert( "Form is validated and in this block api call should be made..." ); } } > |
Step 9: Also, here we can have validationSchema prop which takes the Yup object (in this case LoginSchema) as a parameter with customized validations like if we want our Field to be :
- String : Yup.string()
- Format as email (validation message) : Yup.email(“Invalid email address format”)
- Minimum characters : Yup.min(length , “Validation Message”)
- Maximum characters : Yup.max(length , “Validation Message”)
Javascript
const LoginSchema = Yup.object().shape({ email: Yup.string() // Format Validation .email( "Invalid email address format" ) // Required Field Validation .required( "Email is required" ), password: Yup.string() //Minimum Character Validation .min(3, "Password must be 3 characters at minimum" ) .required( "Password is required" ) }); |
Step 10: Formik Component after including 3 props namely initialValues, ValidationSchema (to bind Formik and Yup), onSubmit looks like this :
Javascript
<Formik initialValues={{ email: "" , password: "" }} validationSchema={LoginSchema} onSubmit={(values) => { console.log(values) alert( "Form is validated! Submitting the form..." ); }} > |
The 4 important states of props object are touched, errors , isSubmitting, values which are more than enough to create highly customized forms .
- touched takes boolean values as input and it sets to true if a field is clicked.
- errors is used to display error messages set by the Yup object.
- isSubmitting is set to true after we click on submit the form.
- values consist of all field values at that point in time.
Step 11: Now comes the ErrorMessage Component which we generally use below the Field Component to display the validation generated by Yup. We can add bootstrap class invalid-feedback for styling.
Javascript
<label htmlFor= "email" >Email</label> <Field type= "email" name= "email" placeholder= "Enter email" autocomplete= "off" className={`mt-2 form-control ${touched.email && errors.email ? "is-invalid" : "" }`} // If there is validation error then // is-invalid bootstrap class is added /> <ErrorMessage component= "div" name= "email" className= "invalid-feedback" /> |
Step 12: We haven’t used isSubmitting prop in the function just yet. We can do one interesting thing using it. We can acknowledge the user who has been logged in and display his username and password using the values parameter on the screen by using conditional rendering and ternary operator.
Javascript
isSubmitting ? (<h1>Login Page</h1>) : (<h1>Confirmation of Login</h1>) // (condition) ? (if true this component gets displayed) : ( else this component gets displayed) |
Step to Run Application: Run the application using the following command from the root directory of the project:
npm start
Output: Now open your browser and go to http://localhost:3000/, you will see the following output: