Kurs React Native · Moduł 5: Formularze
Walidacja z Yup i Zod
W tej lekcji4
Schematy walidacji pozwalają definiować reguły w jednym miejscu.
Yup
npx expo install yup @hookform/resolversimport { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
// Schema walidacji
const schema = yup.object({
name: yup
.string()
.required('Imię jest wymagane')
.min(2, 'Min. 2 znaki')
.max(50, 'Max. 50 znaków'),
email: yup
.string()
.required('Email jest wymagany')
.email('Nieprawidłowy format email'),
password: yup
.string()
.required('Hasło jest wymagane')
.min(8, 'Min. 8 znaków')
.matches(/[a-z]/, 'Wymagana mała litera')
.matches(/[A-Z]/, 'Wymagana wielka litera')
.matches(/[0-9]/, 'Wymagana cyfra'),
confirmPassword: yup
.string()
.required('Potwierdź hasło')
.oneOf([yup.ref('password')], 'Hasła muszą być identyczne'),
age: yup
.number()
.transform((value) => (isNaN(value) ? undefined : value))
.required('Wiek jest wymagany')
.min(18, 'Musisz mieć min. 18 lat')
.max(120, 'Nieprawidłowy wiek'),
terms: yup
.boolean()
.oneOf([true], 'Musisz zaakceptować regulamin'),
});
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>
{/* Pola formularza z Controller */}
</View>
);
}Zod (alternatywa)
npx expo install zod @hookform/resolversimport { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
const schema = z.object({
name: z
.string()
.min(1, 'Imię jest wymagane')
.min(2, 'Min. 2 znaki'),
email: z
.string()
.min(1, 'Email jest wymagany')
.email('Nieprawidłowy email'),
password: z
.string()
.min(8, 'Min. 8 znaków')
.regex(/[a-z]/, 'Wymagana mała litera')
.regex(/[A-Z]/, 'Wymagana wielka litera')
.regex(/[0-9]/, 'Wymagana cyfra'),
confirmPassword: z.string(),
website: z
.string()
.url('Nieprawidłowy URL')
.optional()
.or(z.literal('')),
}).refine((data) => data.password === data.confirmPassword, {
message: 'Hasła muszą być identyczne',
path: ['confirmPassword'],
});
type FormData = z.infer<typeof schema>;
function ZodForm() {
const { control, handleSubmit } = useForm<FormData>({
resolver: zodResolver(schema),
});
// ...
}Walidacja warunkowa
const schema = yup.object({
hasCompany: yup.boolean(),
companyName: yup.string().when('hasCompany', {
is: true,
then: (schema) => schema.required('Nazwa firmy wymagana'),
otherwise: (schema) => schema.notRequired(),
}),
nip: yup.string().when('hasCompany', {
is: true,
then: (schema) =>
schema
.required('NIP wymagany')
.matches(/^\d{10}$/, 'NIP musi mieć 10 cyfr'),
}),
});Asynchroniczna walidacja
const schema = yup.object({
username: yup
.string()
.required()
.test('unique', 'Nazwa zajęta', async (value) => {
if (!value) return true;
const response = await fetch(`/api/check-username?name=${value}`);
const { available } = await response.json();
return available;
}),
});Schematy walidacji to czytelny i wielokrotnie używalny sposób definiowania reguł!
Kod do tej lekcji: App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { z } from 'zod';
// TODO: stwórz schemat walidacji za pomocą z.object({ ... }):
// - email: z.string().email('Nieprawidłowy email')
// - password: z.string().min(8, 'Min. 8 znaków')
// - confirmPassword: z.string()
// Dodaj .refine(...) sprawdzający, czy password === confirmPassword
// z message: 'Hasła muszą być identyczne' i path: ['confirmPassword']
// TODO: wyprowadź typ z schematu: type FormData = z.infer<typeof schema>
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.text}>
Uzupełnij schemat walidacji Zod powyżej.
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
backgroundColor: '#1a5276',
},
text: {
fontSize: 16,
color: '#aed6f1',
textAlign: 'center',
},
});Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jak połączyć Yup z react-hook-form?
2. Która biblioteka ma lepsze wsparcie TypeScript?
Zadania praktyczne w grze
- Klikanie w kolejności
Kliknij elementy schematu email w Yup:
- Edytor kodu
Uzupełnij schemat z walidacją email, hasła i potwierdzenia.