Условная валидация в схемах Yup — это механизм, позволяющий изменять
правила проверки данных в зависимости от значения других полей. В
контексте YupResolver эта логика сохраняется полностью,
поскольку резолвер лишь передаёт данные валидационной схеме Yup без
изменения её поведения.
Ключевым инструментом реализации условной логики является метод
when, который позволяет описывать зависимости между полями
и динамически менять требования к значению.
whenМетод when используется для создания зависимостей между
полями схемы. Он позволяет реагировать на изменения других значений
формы и изменять правила валидации текущего поля.
Общий синтаксис:
field: yup.string().when('otherField', (otherValue, schema) => {
return otherValue ? schema.required() : schema.notRequired();
})
В этом примере поле становится обязательным только при наличии
значения в otherField.
Рассмотрим классический сценарий: поле “пароль подтверждения” должно быть обязательным только если пользователь ввёл пароль.
import * as yup from 'yup';
const schema = yup.object({
password: yup.string().min(6, 'Минимум 6 символов'),
confirmPassword: yup.string().when('password', (password, schema) => {
if (password) {
return schema.required('Подтверждение обязательно')
.oneOf([yup.ref('password')], 'Пароли должны совпадать');
}
return schema.notRequired();
})
});
Здесь важно понимать:
when получает значение зависимого поля
(password)when поддерживает массив зависимостей. Это позволяет
строить более сложные условия.
age: yup.number().when(['isAdult', 'country'], (isAdult, country, schema) => {
if (isAdult && country === 'KZ') {
return schema.min(21, 'Возраст должен быть не менее 21');
}
return schema.min(18, 'Минимальный возраст 18');
})
В этом случае логика зависит сразу от двух полей. Порядок аргументов соответствует порядку зависимостей.
Более современный и читаемый подход — использование объекта
context:
age: yup.number().when(['isAdult', 'country'], {
is: (isAdult, country) => isAdult && country === 'KZ',
then: (schema) => schema.min(21, 'Возраст 21+'),
otherwise: (schema) => schema.min(18, 'Возраст 18+')
})
Преимущества подхода:
Частый сценарий — динамическое добавление
required().
deliveryAddress: yup.string().when('deliveryType', {
is: 'courier',
then: (schema) => schema.required('Укажите адрес доставки'),
otherwise: (schema) => schema.notRequired()
})
Такая схема часто используется в формах оформления заказов, анкетах и многошаговых формах.
Для чисел when особенно полезен при проверке
диапазонов.
discount: yup.number().when('hasDiscount', {
is: true,
then: (schema) => schema.min(1).max(50),
otherwise: (schema) => schema.oneOf([0])
})
Здесь поле discount либо строго равно 0, либо находится
в диапазоне скидок.
Массивы часто требуют динамических ограничений длины.
tags: yup.array().when('allowMultipleTags', {
is: true,
then: (schema) => schema.min(1, 'Добавьте минимум один тег'),
otherwise: (schema) => schema.max(1, 'Можно выбрать только один тег')
})
Таким образом можно управлять поведением массива без изменения структуры данных.
when корректно работает и во вложенных объектах.
const schema = yup.object({
user: yup.object({
role: yup.string(),
permissions: yup.array().when('role', {
is: 'admin',
then: (schema) => schema.min(5, 'Администратор должен иметь минимум 5 прав'),
otherwise: (schema) => schema.max(2)
})
})
});
При работе с вложенностью важно учитывать путь к полю в объекте.
isФункция is позволяет реализовать сложные условия:
status: yup.string().when(['age', 'country'], {
is: (age, country) => age > 18 && country === 'KZ',
then: (schema) => schema.oneOf(['active', 'verified']),
otherwise: (schema) => schema.oneOf(['guest'])
})
Такая конструкция часто используется для бизнес-правил, зависящих от нескольких факторов одновременно.
YupResolverПри использовании YupResolver в связке с React Hook Form
условная логика работает на этапе валидации схемы.
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
const form = useForm({
resolver: yupResolver(schema)
});
Особенности поведения:
YupResolver не кеширует результаты условийwhen работают на основе текущего состояния
формыВ сложных схемах порядок объявления может влиять на читаемость, но не на исполнение.
Однако важно учитывать:
when, должны быть объявлены в
схемеwhenthis
контекстаНекорректно:
when('field', (value, schema) => {
return this.min(5); // ошибка контекста
})
Корректно:
when('field', (value, schema) => {
return schema.min(5);
})
when(['a', 'b'], (b, a, schema) => {}) // логическая ошибка
Аргументы всегда соответствуют порядку зависимостей.
when вне yup-схемыМетод работает только внутри определения схемы Yup и не может применяться в произвольных функциях.
when
с другими методамиУсловная валидация часто используется вместе с:
test() для кастомных проверокoneOf() для ограниченных списковrequired() для обязательностиnullable() для работы с пустыми значениямиПример комбинированной логики:
email: yup.string()
.email('Некорректный email')
.when('subscribe', {
is: true,
then: (schema) => schema.required('Email обязателен при подписке'),
otherwise: (schema) => schema.notRequired().nullable()
})
В реальных приложениях when используется для
моделирования сложных бизнес-правил:
Пример:
paymentMethod: yup.string().when('country', {
is: (country) => country === 'KZ',
then: (schema) => schema.oneOf(['card', 'kaspi']),
otherwise: (schema) => schema.oneOf(['card', 'paypal'])
})
Хотя when добавляет гибкость, он также увеличивает
сложность схемы.
Рекомендации:
when внутри
whenobject().shape() для логического
разделения схемПри большом количестве условий схема может стать трудно читаемой. В таких случаях полезно:
Пример выделения логики:
const isKZAdult = (age, country) => age > 18 && country === 'KZ';
const schema = yup.object({
age: yup.number().when(['age', 'country'], {
is: isKZAdult,
then: (schema) => schema.min(21),
otherwise: (schema) => schema.min(18)
})
});
Важно учитывать, что when срабатывает даже при
undefined или null.
field: yup.string().when('other', {
is: (val) => !!val,
then: (schema) => schema.required(),
})
Проверка должна учитывать falsy-значения, иначе логика может быть нарушена.
В формах, где поля добавляются или удаляются динамически,
when остаётся стабильным механизмом:
YupResolver автоматически учитывает измененияwhenwhen позволяет перенести бизнес-логику из компонентов
формы в уровень схемы валидации. Это приводит к: