От халепа... Ця сторінка ще не має українського перекладу, але ми вже над цим працюємо!
От халепа... Ця сторінка ще не має українського перекладу, але ми вже над цим працюємо!
Ihor Belehai
/
Front End Developer
5 min read
And so, we return to our series of articles about building forms with React, Typescript, React Hook Form, Material-UI, and Yup. In the previous article, we got acquainted with React Hook Form and created a basic form. Today, we’ll continue building our form by adding a validation with Yup.
As always, if you want to see the final source code of the series, visit the following link.
You can also play with the demo.
Contents
If you want to understand how to smooth out the creation of a form before using Yup, we recommend checking out the previous article. If you are ready to get into the finer details of validation, you’re in the right place.
Let’s go!
npm i yup
2. Then, install types as devDependencies to autocomplete support:
npm i -D @types/yup
Let’s refer to the form schema we built in the previous article:
name – required, min 2 characters, max 120
breed – required, min 2 characters, max 120
description – optional, min 2 characters, max 500
first name – required, min 2 characters, max 120
last name – required, min 2 characters, max 120
phone number – required, correct phone number format
email – optional, valid email format
call me back – checkbox, true/false
With such requirements, building a validation with Yup takes minimal effort. Let’s have a go:
3. Create a file validation.ts in the root of the project
4. Import Yup:
import * as yup from 'yup';
5. Now, create a Yup object to describe our Appointment validation:
export const validationSchema = yup.object().shape({ // here we are going to add a validation of each of our fields });
6. Add validation for each field one by one starting from the title:
// title - required, min 2 characters, max 120 title: yup.string().required().min(2).max(120)
As you see, you can write Yup validation chaining validation rules:
7. As we go forward, let’s describe the validation for the date field:
const today = new Date(); today.setHours(0, 0, 0, 0); // make it today 00:00:00:00 // date - datepicker, required, min date is today date: yup.date().min(today).required()
8. Now let’s take a look at the plan field. The user should choose between two options: Basic and Premium. Let’s make that work:
// selected plan - dropdown, one of Premium/Basic, required plan: yup .string() .oneOf([AppointmentPlan.Basic, AppointmentPlan.Premium]) .required(),
We’ve successfully described some of our validation rules. At this point, our schema should look like this:
export const validationSchema = yup.object().shape({ title: yup.string().required().min(2).max(120), date: yup.date().min(new Date()).required(), plan: yup .string() .oneOf([AppointmentPlan.Basic, AppointmentPlan.Premium]) .required(), });
9. Now, following the previous examples, let’s describe the pet validation:
/* Pet information - name - required, min 2 characters, max 120 - breed - required, min 2 characters, max 120 - description - optional, min 2 characters, max 500 */ pet: yup.object({ name: yup.string().required().min(2).max(120), breed: yup.string().required().min(2).max(120), description: yup.string().min(2).max(120), })
If you want to describe an object, use yup.object(). Moreover, if the field is optional, we just don’t use required().
10. Do the same with the contact object validation:
/* Contact information - first name - required, min 2 characters, max 120 - last name - required, min 2 characters, max 120 - phone number - required, correct phone number format - email - optional, correct email format - call me back - checkbox, true/false */ contact: yup.object({ firstName: yup.string().required().min(2).max(120), lastName: yup.string().required().min(2).max(120), callMeBack: yup.boolean().required(), email: yup.string().email() }),
As you see, yup.string()
has email()
method which allows us to check whether the email has a correct format!
11. The only field left to validate is phoneNumber. We can implement the validation for this field in several ways:
const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/ ... phoneNumber: yup.string().matches(phoneRegExp)
But I’ve given this example just to let you know that it is possible. Meanwhile, I prefer another method:
npm i yup-phone
2. Import into the file with validation schema validation.ts:
import 'yup-phone';
3. Apply it:
phoneNumber: yup.string().phone()
I prefer using yup-phone because it utilizes google-libphonenumber (a library that parses, formats, stores, and validates international phone numbers), which gives accurate validation checks. We don’t have to reinvent the wheel for code created before we needed it.
12. Finally, we’ve finished setting up our validation rules. Now your validation.ts file should look like this:
import * as yup from 'yup'; import { AppointmentPlan } from './models'; import 'yup-phone'; export const validationSchema = yup.object().shape({ title: yup.string().required().min(2).max(120), date: yup.date().min(new Date()).required(), plan: yup .string() .oneOf([AppointmentPlan.Basic, AppointmentPlan.Premium]) .required(), contact: yup.object({ firstName: yup.string().required().min(2).max(120), lastName: yup.string().required().min(2).max(120), phoneNumber: yup.string().phone(), email: yup.string().email(), callMeBack: yup.boolean().required(), }), pet: yup.object({ name: yup.string().required().min(2).max(120), breed: yup.string().required().min(2).max(120), description: yup.string().min(2).max(120), }) });
Looks great. Now we are ready to move on.
Now, it’s time to connect our validation schema with React Hook Form.
npm i @hookform/resolvers
This package contains validation resolvers for React Hook Form. It includes various validation libraries: Yup, Zod, class-validator, and so on.
2. Import yup Resolver into AppointmentForm.TSX along with our brand new validation schema:
import { yupResolver } from '@hookform/resolvers/yup'; import { validationSchema } from '../validation';
3. Use it inside of useForm:
const form: UseFormReturn<Appointment, UseFormProps> = useForm<Appointment>({ defaultValues, // Use yup resolver inside React Hook Form resolver: yupResolver(validationSchema) });
As you can see, that’s quite simple.
You might remember that the previous article discussed a powerful React Hook Form feature — DevTools. Now, we’ll use that to make sure that our validation really works:
title – 1 character
date – yesterday
pet name – ‘Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.’ (123 characters)
2. Press the “Make an appointment” button.
3. Check DevTools and see ERROR Type and MESSAGE properties for invalid fields: