Creating form validation is a tedious but important task. React’s normal construction and validation of forms can be annoying when you need to create a state setting process to submit a form. Formik makes it possible to create a form in simpler ways. Combined with Yup, they help us build the authentication process easier.
Article included
- Setting form fields and init values with Formik
- Handling user inputs
- Create validation with Yup
- Process submisstion form
In this article, I will build a simple registration form and process form validation. It includes full name, email, password and password confirmation fields.
Setting form fields and init values with Formik
Below are examples and signup forms
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import React from "react"; export default function App() { return ( <div className="App"> <h1>Validation with Formik + Yup</h1> <form> <div> <label>Full Name</label> <input type="text" name="full_name" /> </div> <div> <label>Email</label> <input type="email" name="email" /> </div> <div> <label>Password</label> <input type="password" name="password" /> </div> <div> <label>Confirm Password</label> <input type="password" name="confirm_password" /> </div> <div> <button type="submit">Submit</button> </div> </form> </div> ); } |
As you can see, no state is declared to store the values of the fields. We will not use the useState hook for that. Instead, we will use Formik to store them.
Let’s start by installing Formik
1 2 3 4 | npm install formik --save // or yarn add formik |
Formik provides a custom hook that returns all the necessary states and helper, which is called useFormik. It accepts an object that defines the configuration of the form.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import React from "react"; import { useFormik } from "formik"; export default function App() { const formik = useFormik({ initialValues: { full_name: "", email: "", password: "", confirm_password: "" } }); return ( <div className="App"> <h1>Validation with Formik + Yup</h1> <form> <div> <label>Full Name</label> <input type="text" name="full_name" value={formik.values.full_name} /> </div> <div> <label>Email</label> <input type="email" name="email" value={formik.values.email} /> </div> <div> <label>Password</label> <input type="password" name="password" value={formik.values.password} /> </div> <div> <label>Confirm Password</label> <input type="password" name="confirm_password" value={formik.values.confirm_password} /> </div> <div> <button type="submit">Submit</button> </div> </form> </div> ); } |
We pass initialValue
to the form into useFormik. The attribute name declared in initialValue matches the name of <input />
. States are returned and helpers can now be accessed from the formik variable. Thus, we can store the values of the field and put them into our component input: value={formik.values.full_name}
. No need React useState
.
Handling user inputs
The next step would be to capture the user input value and store it in the Formik state. Formik provides us with a series of helper functions, one of which is handleChange
. This function accepts the event
object (returned from onChange) and uses the field name to store the value in the appropriate Formik state.
1 2 3 4 5 6 7 | <input type="text" name="full_name" value={formik.values.full_name} onChange={formik.handleChange} /> |
There is no need to pass the name field to handleChange
as it will get field name = event.target.name
Create validation with Yup
Setting forms and processing their inputs is easy, but validating those values is not. We have to create a validator to validate all the fields. But thanks to Yup, we can create validation processes more easily.
What is Yup? Excerpt from the Yup document page:
“Yup is a JavaScript schema builder for value parsing and validation”
Translated as: “Yup is a Javascript schema for validating and validating analysis”. We can use Yup to create a validation schema and apply it with useFormik
. Formik has an option for Yup called validationSchema
.
First, install Yup:
1 2 3 4 | npm install yup --save // or yarn add yup |
We can then import Yup on the signup page above and create validation schema for our form:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import React from "react"; import { useFormik } from "formik"; import * as Yup from "yup"; export default function App() { const formik = useFormik({ initialValues: { full_name: "", email: "", password: "", confirm_password: "" }, validationSchema: Yup.object({ full_name: Yup.string() .min(2, "Mininum 2 characters") .max(15, "Maximum 15 characters") .required("Required!"), email: Yup.string() .email("Invalid email format") .required("Required!"), password: Yup.string() .min(8, "Minimum 8 characters") .required("Required!"), confirm_password: Yup.string() .oneOf([Yup.ref("password")], "Password's not match") .required("Required!") }) }); return ( <div className="App"> <h1>Validation with Formik + Yup</h1> <form> <div> <label>Full Name</label> <input type="text" name="full_name" value={formik.values.full_name} onChange={formik.handleChange} /> {formik.errors.full_name && formik.touched.full_name && ( <p>{formik.errors.full_name}</p> )} </div> <div> <label>Email</label> <input type="email" name="email" value={formik.values.email} onChange={formik.handleChange} /> {formik.errors.email && formik.touched.email && ( <p>{formik.errors.email}</p> )} </div> <div> <label>Password</label> <input type="password" name="password" value={formik.values.password} onChange={formik.handleChange} /> {formik.errors.password && formik.touched.password && ( <p>{formik.errors.password}</p> )} </div> <div> <label>Confirm Password</label> <input type="password" name="confirm_password" value={formik.values.confirm_password} onChange={formik.handleChange} /> {formik.errors.confirm_password && formik.touched.confirm_password && ( <p>{formik.errors.confirm_password}</p> )} </div> <div> <button type="submit">Submit</button> </div> </form> </div> ); } |
There are 2 things I have done above, that is create a validation scheme with Yup and display error messages.
Create the validation schema with Yup
As you saw above, our schema is quite simple. We just chain the authentication functions to form a set of authentication schemes. For example, we want the value of full_name
not be blank, be a string, have at least 2 characters and have a maximum of 15 characters. Then, with Yup, we can use the required
, string
, min
and max
. Error messages can be passed to each function.
The slightly more complex authentication that we often encounter is email authentication and password authentication. Fortunately, Yup also provides us with functions for email authentication and equivalent values. There are many great functions that Yup provides, you can find it in the Yup document page
Show the error messages
The useFormik hook returns errors
and the touched
state is used to display error messages.
errors
: 1 object of form’s validation error.touched
: 1 object with boolean data type indicating whether the field has been accessed or not.
The formik valdation function runs on each user input key combination. That means errors
object will contain all validation errors at any time. So we can display an error message like this:
1 2 | {formik.errors.full_name && <p>{formik.errors.full_name}</p>} |
The above code will display the error message as soon as they enter the content into a field. Normally we want the error mess to show up after the user has finished typing. That’s why we need touched
state:
1 2 3 4 | {formik.errors.full_name && formik.touched.full_name && ( <p>{formik.errors.full_name}</p> )} |
By checking the touched
state, we can now show the error message after the user has entered the field.
Handling form submission
To handle the form submission, we need to pass the onSubmit
option to the useFormik
hook. We can access the submitted values in the onSubmit
function. You can do whatever you want with the values, such as using it as the payload to the API.
1 2 3 4 5 6 7 8 9 10 11 12 | const formik = useFormik({ initialValues: { ... }, validationSchema: Yup.object({ ... }), onSubmit: values => { alert(JSON.stringify(values, null, 2)); } }); |
Another helper function that Formik provides is handleSubmit. It will execute the onSubmit
function if there is no validation error. We can put the handleSubmit
function in <form />
.
1 2 | <form onSubmit={formik.handleSubmit}> |
Below is the complete code of the SignUp form and its validation with Formik + Yup.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import React from "react"; import { useFormik } from "formik"; import * as Yup from "yup"; export default function App() { const formik = useFormik({ initialValues: { full_name: "", email: "", password: "", confirm_password: "" }, validationSchema: Yup.object({ full_name: Yup.string() .min(2, "Mininum 2 characters") .max(15, "Maximum 15 characters") .required("Required!"), email: Yup.string() .email("Invalid email format") .required("Required!"), password: Yup.string() .min(8, "Minimum 8 characters") .required("Required!"), confirm_password: Yup.string() .oneOf([Yup.ref("password")], "Password's not match") .required("Required!") }), onSubmit: values => { alert(JSON.stringify(values, null, 2)); } }); return ( <div className="App"> <h1>Validation with Formik + Yup</h1> <form onSubmit={formik.handleSubmit}> <div> <label>Full Name</label> <input type="text" name="full_name" value={formik.values.full_name} onChange={formik.handleChange} /> {formik.errors.full_name && formik.touched.full_name && ( <p>{formik.errors.full_name}</p> )} </div> <div> <label>Email</label> <input type="email" name="email" value={formik.values.email} onChange={formik.handleChange} /> {formik.errors.email && formik.touched.email && ( <p>{formik.errors.email}</p> )} </div> <div> <label>Password</label> <input type="password" name="password" value={formik.values.password} onChange={formik.handleChange} /> {formik.errors.password && formik.touched.password && ( <p>{formik.errors.password}</p> )} </div> <div> <label>Confirm Password</label> <input type="password" name="confirm_password" value={formik.values.confirm_password} onChange={formik.handleChange} /> {formik.errors.confirm_password && formik.touched.confirm_password && ( <p>{formik.errors.confirm_password}</p> )} </div> <div> <button type="submit">Submit</button> </div> </form> </div> ); } |
link code sandbox: https://codesandbox.io/s/react-formik-yup-y37yq?from-embed
Epilogue
The above is a small example of validation form using Formik and Yup. Hopefully this article will help you in the process of improving your React skills. Thanks for visiting.
Reference: https://medium.com/javascript-in-plain-english/react-form-validation-with-formik-yup-ee6395b355f