У меня есть поле электронной почты, которое отображается только в том случае, если установлен флажок (логическое значение - true). Когда форма отправляется, я только то, что это поле должно быть обязательным, если флажок установлен (логическое значение истинно).
Это то, что я пробовал до сих пор:
const validationSchema = yup.object().shape({
email: yup
.string()
.email()
.label('Email')
.when('showEmail', {
is: true,
then: yup.string().required('Must enter email address'),
}),
})
Я пробовал несколько других вариантов, но получаю ошибки от Formik и Yup:
Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
at yupToFormErrors (formik.es6.js:6198)
at formik.es6.js:5933
at <anonymous>
yupToFormErrors @ formik.es6.js:6198
И я также получаю ошибки проверки от Yup. Что я делаю неправильно?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вероятно, вы не определяете правило проверки для поля showEmail.
Я сделал CodeSandox, чтобы проверить это, и как только добавил:
showEmail: yup.boolean()
Форма начала валидацию правильно, и ошибок не было.
Это URL: https://codesandbox.io/s/74z4px0k8q
И на будущее это была правильная схема проверки:
validationSchema = {yup.object().shape({
showEmail: yup.boolean(),
email: yup
.string()
.email()
.when("showEmail", {
is: true,
then: yup.string().required("Must enter email address")
})
})
}
Вы добавите конкретный тест к ключу is, используя функцию: is: (emailValue) => emailValue === "некоторая тестовая строка, которой вы хотите сопоставить"
Спасибо за ответ, я действительно понятия не имею, как вы пришли к этому решению, но это отражает серьезную проблему со многими пакетами npm, то есть 90 процентов документации библиотеки должно быть извлечено из вопросов Git или ответов SO.
Обновлены коды и ящик codeandbox.io/s/formik-conditional-val-1ldmx
Полностью согласен с ответом @ João Cunha. Просто дополнение к варианту использования радиокнопки.
Когда мы используем радиокнопку в качестве условия, мы можем проверять значение строки вместо логического. например is: 'Phone'
const ValidationSchema = Yup.object().shape({
// This is the radio button.
preferredContact: Yup.string()
.required('Preferred contact is required.'),
// This is the input field.
contactPhone: Yup.string()
.when('preferredContact', {
is: 'Phone',
then: Yup.string()
.required('Phone number is required.'),
}),
// This is another input field.
contactEmail: Yup.string()
.when('preferredContact', {
is: 'Email',
then: Yup.string()
.email('Please use a valid email address.')
.required('Email address is required.'),
}),
});
Это переключатель, написанный на ReactJS, метод onChange является ключом для запуска проверки условий.
<label>
<input
name = "preferredContact" type = "radio" value = "Email"
checked = {this.state.preferredContact == 'Email'}
onChange = {() => this.handleRadioButtonChange('Email', setFieldValue)}
/>
Email
</label>
<label>
<input
name = "preferredContact" type = "radio" value = "Phone"
checked = {this.state.preferredContact == 'Phone'}
onChange = {() => this.handleRadioButtonChange('Phone', setFieldValue)}
/>
Phone
</label>
А вот функция обратного вызова при изменении переключателя. если мы используем Formik, setFieldValue - это то, что вам нужно.
handleRadioButtonChange(value, setFieldValue) {
this.setState({'preferredContact': value});
setFieldValue('preferredContact', value);
}
Автор формик тут ...
Чтобы Yup.when работал правильно, вам нужно добавить showEmail в initialValues и в форму схемы Yup.
В общем, при использовании validationSchema рекомендуется убедиться, что все поля вашей формы имеют начальные значения, чтобы Yup мог их сразу увидеть.
Результат будет выглядеть так:
<Formik
initialValues = {{ email: '', showEmail: false }}
validationSchema = {Yup.object().shape({
showEmail: Yup.boolean(),
email: Yup
.string()
.email()
.when("showEmail", {
is: true,
then: Yup.string().required("Must enter email address")
})
})
}
/>
Вы даже можете использовать функцию для сложных случаев. Функциональный регистр помогает при сложных проверках
validationSchema = {yup.object().shape({
showEmail: yup.boolean(),
email: yup
.string()
.email()
.when("showEmail", (showEmail) => {
if (showEmail)
return yup.string().required("Must enter email address")
})
})
}email: Yup.string()
.when(['showEmail', 'anotherField'], {
is: (showEmail, anotherField) => {
return (showEmail && anotherField);
},
then: Yup.string().required('Must enter email address')
}),
Как это будет работать с тремя возможными значениями showEmail? Т.е. вместо логического () это была строка ()