Formik часто применяется как слой управления состоянием формы, а Yup выступает декларативным механизмом описания схемы валидации. Их связка позволяет отделить логику проверки данных от компонентов интерфейса и минимизировать количество императивного кода в обработчиках событий.
Основная модель взаимодействия строится вокруг передачи схемы Yup в
параметр validationSchema у Formik. В этом случае Formik
автоматически выполняет валидацию при изменении значений, потере фокуса
или отправке формы, в зависимости от конфигурации.
Yup предоставляет цепочечный API для описания структуры данных формы. Каждое поле описывается через соответствующий тип:
string() — строковые значенияnumber() — числовые значенияboolean() — логические значенияdate() — датыarray() — массивыobject() — вложенные структурыПростейшая схема для формы регистрации может выглядеть следующим образом:
import * as Yup from "yup";
const schema = Yup.object({
email: Yup.string()
.email("Некорректный формат email")
.required("Email обязателен"),
password: Yup.string()
.min(8, "Минимум 8 символов")
.required("Пароль обязателен")
});
Каждое правило в цепочке добавляет ограничение, а строковые аргументы задают сообщение об ошибке.
Formik принимает схему через свойство validationSchema.
После этого ручное описание функции validate становится
избыточным.
import { Formik, Form, Field, ErrorMessage } from "formik";
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={schema}
onSub mit={(values) => {
console.log(values);
}}
>
<Form>
<Field name="email" />
<ErrorMessage name="email" />
<Field name="password" type="password" />
<ErrorMessage name="password" />
<button type="submit">Отправить</button>
</Form>
</Formik>
Formik синхронизирует значения формы с Yup-схемой и формирует объект
ошибок, который доступен через errors.
Результат валидации Yup представляет собой объект, где ключи
соответствуют полям формы. Formik использует его для отображения ошибок
и управления состоянием touched.
Пример структуры:
{
email: "Некорректный формат email",
password: "Минимум 8 символов"
}
Ошибки отображаются только для полей, помеченных как
touched, что предотвращает преждевременный вывод
сообщений.
Yup.string()
.required()
.min(3)
.max(20)
.matches(/^[a-zA-Z]+$/)
Yup.number()
.required()
.min(0)
.max(100)
.integer()
Yup.string().email()
Yup.string().url()
Механизм when позволяет строить зависимости между
полями. Это используется в сценариях, где одно поле влияет на правила
другого.
Yup.object({
password: Yup.string().required(),
confirmPassword: Yup.string().when("password", (password, schema) => {
return schema.oneOf([password], "Пароли должны совпадать");
})
});
Более сложный пример с несколькими зависимостями:
Yup.string().when(["role", "isActive"], (role, isActive, schema) => {
if (role === "admin" && isActive) {
return schema.required("Обязательно для активного администратора");
}
return schema;
});
Formik поддерживает вложенные структуры через точечную нотацию, а Yup
описывает их через object.
const schema = Yup.object({
user: Yup.object({
name: Yup.string().required(),
age: Yup.number().min(18)
})
});
Доступ к значениям в Formik:
<Field name="user.name" />
<Field name="user.age" />
Для динамических списков используется Yup.array. Это
особенно важно при использовании FieldArray в Formik.
const schema = Yup.object({
tags: Yup.array()
.of(Yup.string().required("Тег не может быть пустым"))
.min(1, "Добавить минимум один тег")
});
Сложный вариант с объектами:
Yup.array().of(
Yup.object({
title: Yup.string().required(),
quantity: Yup.number().min(1)
})
);
Метод test позволяет реализовать пользовательские
проверки, включая асинхронные операции, например запросы к API.
Yup.string().test(
"check-username",
"Имя уже занято",
async (value) => {
const response = await fetch(`/api/check?username=${value}`);
const data = await response.json();
return data.available;
}
);
Асинхронная валидация требует осторожности: частые запросы могут создавать нагрузку, поэтому часто применяется debounce на уровне UI.
Метод test также используется для синхронной логики:
Yup.number().test(
"even-number",
"Число должно быть чётным",
(value) => value % 2 === 0
);
Можно создавать цепочки проверок с доступом к контексту:
Yup.string().test(
"starts-with",
function (value) {
const prefix = this.options.context?.prefix;
return value.startsWith(prefix);
}
);
Yup позволяет преобразовывать входные данные до валидации.
Yup.number()
.transform((value, originalValue) => {
return String(originalValue).trim() === "" ? null : value;
})
.nullable();
Типичный кейс — обработка пустых строк как null или
undefined.
Схемы можно компоновать и переиспользовать, что снижает дублирование логики.
const baseString = Yup.string().trim().required();
const schema = Yup.object({
firstName: baseString,
lastName: baseString
});
Также возможна композиция через concat:
const a = Yup.string().min(3);
const b = Yup.string().max(10);
const combined = a.concat(b);
Yup предоставляет вывод типов через InferType, что
позволяет синхронизировать форму и типы данных.
import * as Yup from "yup";
const schema = Yup.object({
email: Yup.string().email().required(),
age: Yup.number().required()
});
type FormValues = Yup.InferType<typeof schema>;
Это уменьшает риск расхождения между схемой и типами в коде компонента.
Yup.object({
password: Yup.string().required(),
confirmPassword: Yup.string().oneOf(
[Yup.ref("password")],
"Пароли не совпадают"
)
});
Yup.object({
hasCompany: Yup.boolean(),
companyName: Yup.string().when("hasCompany", {
is: true,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired()
})
});
При больших формах с десятками полей схема Yup может становиться тяжёлой. Основные факторы влияния:
test-проверокДля оптимизации используется мемоизация схем и вынос за пределы компонента, чтобы избежать повторного создания объекта при каждом рендере.
Formik пересчитывает валидацию при изменении
initialValues и values. При интеграции с
внешними источниками данных (API, глобальные состояния) важно
учитывать:
when требуют стабильной структуры
данныхВ крупных приложениях схема Yup часто разбивается на модули:
Такой подход снижает связность и упрощает сопровождение, особенно при повторном использовании логики в нескольких формах.
Formik и Yup в связке формируют декларативную модель валидации, где бизнес-правила отделены от интерфейсной логики, а структура данных формализована через единый источник истины.