Validation with Yup
What is Yup?
Yup is a JavaScript object schema validator.
Lets understand the above definition with an example. Consider everday common feature of login form with fields "username" and "password". Before submitting form we want to verify that user has entered all fields. A Valid object should look something like shown below
const loginObj = {username: "abcd",password: "123456"};
What we have here is expected schema for login form. And we know fields "username" and "password" are mandatory, so we have validations on those fields.
Once we have object schema and validation, we can use "Yup" lib to verify if any given object satisfies the schema and validations
How It works?
Simplest way to use Yup
- Define object schema and its validation
- Create validator object using Yup with expected schema and validation
- Use Yup utility function "validate" to verify if object are valid(satisfies schema and validations)
Lets take a case in which we need to work with "car" objects with properties as shown below.
const car = {year: 200,model: "Hyundai",engine: "Petrol",price: 2000};
For a car object to be valid following criteria should be met
- "model" and "engine" property should be of type string
- "year" and "price" property should be of type number
- Except "price" all the other properties are mandatory
The validator object
Now we will create validator object for "car" object
const yup = require("yup");const yupObject = yup.object().shape({price: yup.number(),year: yup.number().required(),model: yup.string().required(),engine: yup.string().required()});
I think above code is pretty self explanatory. It is similar to how we define proptypes in react.
Verify
Next validate "car" object created above using "validate" method on yup object.
yupObject.validate(car).then(function(value) {console.log(value); // returns car object}).catch(function(err) {console.log(err);});
"validate" method returns promise which returns same object if the passed object is valid, in case of invalid "car" object it returns error object with message.
const car = {year: 200,model: "Hyundai"};yupObject.validate(car); //ValidationError: engine is a required field
Chaining of validations
We can chain validation as shown below
const yup = require("yup");const schemaValidatorObject = yup.object().shape({year: yup.number().required().min(2000).max(2018)});
Custom Validation
Many times we need to go beyond simple validation provided by library and write custom validation.
Ex: Lets say if we want to test whether beverge is tea or not
let customValidation = yup.object().shape({beverage: yup.string().test("is-tea", "${path} is not tea", value => value === "tea")});await customValidation.validate({ beverage: "tea" });
Async Validation
To make a validation async return a promise that resolves true or false or a ValidationError
let orderTea = yup.object().shape({bevrage: yup.string().test("is-tea","${path} is not tea",async value => (await value) === "tea")});await orderTea.validate({ bevrage: "coffee" }); // returns Error
Note: In order to allow asynchronous custom validations all (or no) tests are run asynchronously. A consequence of this is that test execution order cannot be guaranteed
Dependent Validation
Suppose validation on a field is dependent on value of other field. In example shown below we want
tea
field to be mandatory only if isMorning
is true.
const schema = object({isMorning: boolean(),tea: string().when("isMorning", {is: true,then: yup.required()})});
Similarly we can add validation which is dependent on multiple fields by passing an array of strings
const schema = yup.object().shape({isMorning: yup.boolean(),isSunday: yup.boolean(),coffee: yup.number().when(["isMorning", "isSunday"], {is: (isMorning, isSunday) => {//any complex calulationreturn isMorning && !isSunday;},then: yup.number().required()})});
Yup no coffee on sunday morning
Yup in Formik
It very simple to use Yup
with formik
. We just need to pass the validator object
to formik
's validationSchema
option. All the Yup
's validation errors are transformed
into formik
state variables. Which can be used to show error messages.
import { Formik } from "formik";import * as Yup from "yup";const SignupSchema = Yup.object().shape({email: Yup.string().email("Invalid email").required("Required")});<FormikinitialValues={{email: ""}}validationSchema={SignupSchema}>...</Formik>;
Ending Note
I hope this gives you good understanding of how Yup works and helps you in getting started. You can try above mentioned examples here(https://runkit.com/pratik14/yup-examples)