Cours React Native · Module 5: Formulaires
Validation avec Yup et Zod
Dans cette leçon4
Les schémas de validation te permettent de définir les règles en un seul endroit.
Yup
npx expo install yup @hookform/resolversimport { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
// Schéma de validation
const schema = yup.object({
name: yup
.string()
.required('Le nom est obligatoire')
.min(2, 'Min. 2 caractères')
.max(50, 'Max. 50 caractères'),
email: yup
.string()
.required('L\'email est obligatoire')
.email('Format d\'email invalide'),
password: yup
.string()
.required('Le mot de passe est obligatoire')
.min(8, 'Min. 8 caractères')
.matches(/[a-z]/, 'Minuscule requise')
.matches(/[A-Z]/, 'Majuscule requise')
.matches(/[0-9]/, 'Chiffre requis'),
confirmPassword: yup
.string()
.required('Confirme le mot de passe')
.oneOf([yup.ref('password')], 'Les mots de passe doivent correspondre'),
age: yup
.number()
.transform((value) => (isNaN(value) ? undefined : value))
.required('L\'âge est obligatoire')
.min(18, 'Tu dois avoir au moins 18 ans')
.max(120, 'Âge invalide'),
terms: yup
.boolean()
.oneOf([true], 'Tu dois accepter les conditions'),
});
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>
{/* Champs du formulaire avec 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, 'Le nom est obligatoire')
.min(2, 'Min. 2 caractères'),
email: z
.string()
.min(1, 'L\'email est obligatoire')
.email('Email invalide'),
password: z
.string()
.min(8, 'Min. 8 caractères')
.regex(/[a-z]/, 'Minuscule requise')
.regex(/[A-Z]/, 'Majuscule requise')
.regex(/[0-9]/, 'Chiffre requis'),
confirmPassword: z.string(),
website: z
.string()
.url('URL invalide')
.optional()
.or(z.literal('')),
}).refine((data) => data.password === data.confirmPassword, {
message: 'Les mots de passe doivent correspondre',
path: ['confirmPassword'],
});
type FormData = z.infer<typeof schema>;
function ZodForm() {
const { control, handleSubmit } = useForm<FormData>({
resolver: zodResolver(schema),
});
// ...
}Validation conditionnelle
const schema = yup.object({
hasCompany: yup.boolean(),
companyName: yup.string().when('hasCompany', {
is: true,
then: (schema) => schema.required('Nom de l\'entreprise requis'),
otherwise: (schema) => schema.notRequired(),
}),
taxId: yup.string().when('hasCompany', {
is: true,
then: (schema) =>
schema
.required('Numéro fiscal requis')
.matches(/^\d{10}$/, 'Le numéro fiscal doit comporter 10 chiffres'),
}),
});Validation asynchrone
const schema = yup.object({
username: yup
.string()
.required()
.test('unique', 'Nom d\'utilisateur déjà pris', async (value) => {
if (!value) return true;
const response = await fetch(`/api/check-username?name=${value}`);
const { available } = await response.json();
return available;
}),
});Les schémas de validation sont une façon lisible et réutilisable de définir les règles !
Code de cette leçon : App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { z } from 'zod';
// TODO : crée un schéma de validation avec z.object({ ... }) :
// - email: z.string().email('Email invalide')
// - password: z.string().min(8, 'Min. 8 caractères')
// - confirmPassword: z.string()
// Ajoute .refine(...) qui vérifie si password === confirmPassword
// avec message: 'Les mots de passe doivent correspondre' et path: ['confirmPassword']
// TODO : dérive le type à partir du schéma : type FormData = z.infer<typeof schema>
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.text}>
Complète le schéma de validation Zod ci-dessus.
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
backgroundColor: '#1a5276',
},
text: {
fontSize: 16,
color: '#aed6f1',
textAlign: 'center',
},
});Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Comment connecte-t-on Yup à react-hook-form ?
2. Quelle bibliothèque offre le meilleur support de TypeScript ?
Tâches pratiques dans le jeu
- Clique dans l'ordre
Clique les éléments d'un schéma email en Yup :
- Éditeur de code
Complète le schéma avec la validation de l'email, du mot de passe et de sa confirmation.