React Native course ยท Module 5: Forms
Validation with Yup and Zod
In this lesson4
Validation schemas allow you to define rules in one place.
Yup
npx expo install yup @hookform/resolversimport { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
// Validation schema
const schema = yup.object({
name: yup
.string()
.required('Name is required')
.min(2, 'Min. 2 characters')
.max(50, 'Max. 50 characters'),
email: yup
.string()
.required('Email is required')
.email('Invalid email format'),
password: yup
.string()
.required('Password is required')
.min(8, 'Min. 8 characters')
.matches(/[a-z]/, 'Lowercase letter required')
.matches(/[A-Z]/, 'Uppercase letter required')
.matches(/[0-9]/, 'Digit required'),
confirmPassword: yup
.string()
.required('Confirm password')
.oneOf([yup.ref('password')], 'Passwords must match'),
age: yup
.number()
.transform((value) => (isNaN(value) ? undefined : value))
.required('Age is required')
.min(18, 'You must be at least 18')
.max(120, 'Invalid age'),
terms: yup
.boolean()
.oneOf([true], 'You must accept the terms'),
});
type FormData = yup.InferType<typeof schema>;
function YupForm() {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
name: '',
email: '',
password: '',
confirmPassword: '',
age: undefined,
terms: false,
},
});
return (
<View>
{/* Form fields with Controller */}
</View>
);
}Zod (alternative)
npx expo install zod @hookform/resolversimport { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
const schema = z.object({
name: z
.string()
.min(1, 'Name is required')
.min(2, 'Min. 2 characters'),
email: z
.string()
.min(1, 'Email is required')
.email('Invalid email'),
password: z
.string()
.min(8, 'Min. 8 characters')
.regex(/[a-z]/, 'Lowercase letter required')
.regex(/[A-Z]/, 'Uppercase letter required')
.regex(/[0-9]/, 'Digit required'),
confirmPassword: z.string(),
website: z
.string()
.url('Invalid URL')
.optional()
.or(z.literal('')),
}).refine((data) => data.password === data.confirmPassword, {
message: 'Passwords must match',
path: ['confirmPassword'],
});
type FormData = z.infer<typeof schema>;
function ZodForm() {
const { control, handleSubmit } = useForm<FormData>({
resolver: zodResolver(schema),
});
// ...
}Conditional Validation
const schema = yup.object({
hasCompany: yup.boolean(),
companyName: yup.string().when('hasCompany', {
is: true,
then: (schema) => schema.required('Company name required'),
otherwise: (schema) => schema.notRequired(),
}),
taxId: yup.string().when('hasCompany', {
is: true,
then: (schema) =>
schema
.required('Tax ID required')
.matches(/^\d{10}$/, 'Tax ID must have 10 digits'),
}),
});Asynchronous Validation
const schema = yup.object({
username: yup
.string()
.required()
.test('unique', 'Username taken', async (value) => {
if (!value) return true;
const response = await fetch(`/api/check-username?name=${value}`);
const { available } = await response.json();
return available;
}),
});Validation schemas are a readable and reusable way to define rules!
Code for this lesson: App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { z } from 'zod';
// TODO: create a validation schema using z.object({ ... }):
// - email: z.string().email('Invalid email')
// - password: z.string().min(8, 'Min. 8 characters')
// - confirmPassword: z.string()
// Add .refine(...) checking whether password === confirmPassword
// with message: 'Passwords must match' and path: ['confirmPassword']
// TODO: derive the type from the schema: type FormData = z.infer<typeof schema>
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.text}>
Complete the Zod validation schema above.
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
backgroundColor: '#1a5276',
},
text: {
fontSize: 16,
color: '#aed6f1',
textAlign: 'center',
},
});Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How do you connect Yup with react-hook-form?
2. Which library has better TypeScript support?
Hands-on tasks in the game
- Click in order
Click the elements of an email schema in Yup:
- Code editor
Complete the schema with email, password and confirmation validation.