Основы Yup и его типов
Официальная документация по Yup — это чудесный источник вдохновения. Но давайте упростим всё прямо сейчас.
Библиотека Yup предоставляет нам возможность валидировать данные через создание схемы. Например:
import * as Yup from "yup";
// Простая схема валидации
const loginValidationSchema = Yup.object({
email: Yup.string().email("Неверный формат email").required("Email обязателен"),
password: Yup.string()
.min(6, "Пароль должен содержать минимум 6 символов")
.required("Пароль обязателен"),
});
Здесь мы проверяем два поля: email и password. Валидация происходит на уровне схемы, а Yup автоматически выбрасывает сообщения об ошибках, если правила нарушены.
Но что, если мы хотим добавить строгую типизацию?
Типизация Yup-схемы с TypeScript
Чтобы типизировать данные нашей формы и использовать их позже (например, при обработке ошибок), нужно создать интерфейс, представляющий структуру данных нашей формы.
// Описание интерфейса данных формы
interface LoginFormValues {
email: string;
password: string;
}
// Присваиваем интерфейс схеме валидации
const loginValidationSchema: Yup.SchemaOf<LoginFormValues> = Yup.object({
email: Yup.string().email("Неверный формат email").required("Email обязателен"),
password: Yup.string()
.min(6, "Пароль должен содержать минимум 6 символов")
.required("Пароль обязателен"),
});
Обратите внимание, как мы используем Yup.SchemaOf<LoginFormValues> для строгой типизации схемы. Теперь, если вы попытаетесь добавить несуществующий ключ, TypeScript вернёт вам ошибку ещё до выполнения кода. А это означает меньше багов и больше счастья.
Создание сложных правил валидации
Теперь, когда мы знаем, как типизировать схемы, добавим немного сложности. Например, предположим, что у нас есть форма регистрации, где требуется проверка подтверждения пароля.
interface RegisterFormValues {
email: string;
password: string;
confirmPassword: string;
}
const registerValidationSchema: Yup.SchemaOf<RegisterFormValues> = Yup.object({
email: Yup.string().email("Неверный формат email").required("Email обязателен"),
password: Yup.string()
.min(6, "Пароль должен содержать минимум 6 символов")
.required("Пароль обязателен"),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password")], "Пароли должны совпадать")
.required("Подтвердите пароль"),
});
Обратите внимание на метод Yup.ref("password"). Он позволяет ссылаться на значение другого поля, чтобы сравнить данные. В данном случае мы проверяем, чтобы confirmPassword соответствовал введённому password.
Обработка ошибок с помощью Formik и Yup
Когда пользователь вводит данные, ошибки валидации могут сделать жизнь проще, а могут вызвать антипатию к вашему приложению. Мы же хотим, чтобы наши пользователи были в восторге! Для этого нужно показать внятные ошибки. Formik делает это легко:
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
// Определяем интерфейс формы
interface LoginFormValues {
email: string;
password: string;
}
// Схема валидации
const loginValidationSchema: Yup.SchemaOf<LoginFormValues> = Yup.object({
email: Yup.string().email("Неверный формат email").required("Email обязателен"),
password: Yup.string()
.min(6, "Пароль должен содержать минимум 6 символов")
.required("Пароль обязателен"),
});
const LoginForm = () => {
const initialValues: LoginFormValues = { email: "", password: "" };
return (
<Formik
initialValues={initialValues}
validationSchema={loginValidationSchema}
onSubmit={(values) => {
console.log("Данные формы:", values);
}}
>
{({ isSubmitting }) => (
<Form>
<div>
<label htmlFor="email">Email:</label>
<Field name="email" type="email" />
<ErrorMessage name="email" component="div" />
</div>
<div>
<label htmlFor="password">Пароль:</label>
<Field name="password" type="password" />
<ErrorMessage name="password" component="div" />
</div>
<button type="submit" disabled={isSubmitting}>
Войти
</button>
</Form>
)}
</Formik>
);
};
export default LoginForm;
Что здесь происходит?
<ErrorMessage />: Formik предоставляет компонент для отображения сообщений об ошибках. В приведённом примере ошибки показываются, если они существуют для поля.- Типизация: мы точно знаем, что данные формы соответствуют интерфейсу
LoginFormValues, и можем безопасно использовать их при отправке. - Валидация в реальном времени: каждый раз, когда пользователь меняет данные, Yup проверяет их, а Formik автоматически обновляет ошибки.
Отображение пользовательских сообщений об ошибках
Вы можете настроить отображение сообщений об ошибках, чтобы сделать их более дружелюбными или заметными. Например:
<ErrorMessage
name="email"
render={(msg) => <div style={{ color: "red" }}>{msg}</div>}
/>
Или даже заменить стандартные сообщения на эмодзи, чтобы разрядить атмосферу:
<ErrorMessage
name="password"
render={(msg) => (
<div style={{ color: "orange" }}>⚠️ {msg}</div>
)}
/>
Типичные ошибки и как их избежать
Один из самых распространённых ошибок — это несоответствие интерфейса данных и схемы валидации. Например, если вы добавите новое поле в интерфейс, но забудете обновить схему, TypeScript предупредит вас.
Ещё одной проблемой может стать отсутствие обработки ошибок. Если сообщения не отображаются для пользователя, вполне возможно, что ошибка в имени поля или компоненте <ErrorMessage />.
Реальное применение знаний
Итак, валидация — это не просто фишка, это основа пользовательского опыта. Будь то форма регистрации, входа или сложная многошаговая форма, грамотная типизация правил и обработка ошибок значительно упрощают разработку и делают интерфейсы дружелюбнее.
На собеседованиях синьоров особенно любят спрашивать про типизацию сложных форм. Упомяните Yup и TypeScript, и вы получите бонусные очки за техническую эрудицию.
Не забывайте комбинировать типы, схемы и обработку ошибок для создания безупречных приложений, которые полюбят пользователи (и их тестировщики). Успехов в реализации будущих форм!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ