英文:
Why is YUP conditional validation causing branch is not a function at Condition.fn error
问题
我有一个 MUIRadioGroup(选项为 Low、Medium 和 High)和一个多选的 MUIAutocomplete 组件在我的表单上。
<MUIRadioGroup
name="requestDetail.riskAssesmentDetail.riskClassification"
label="Risk Classification"
variant="outlined"
size="small"
defaultValue
/>
<MUIAutocomplete
name="requestDetail.riskAssesmentDetail.safetyDetail.investigationType"
label="Type of Investigation"
variant="outlined"
size="small"
multiple
disableCloseOnSelect
options={API_Safety_InvestigationType}
/>
我的模式是...
requestDetail: yup.object().shape({
riskAssesmentDetail: yup.object().shape({
riskClassification: yup
.string()
.label("Risk Classification")
.required()
.typeError("Invalid Selection"),
safetyDetail: yup
.object()
.shape()
.when("riskClassification", {
is: (riskClassification) =>
["Medium", "High"].includes(riskClassification),
then: yup.object({
investigationType: yup
.array()
.label("Type of Investigation")
.min(1),
}),
}),
}),
当单选按钮为 "Medium" 或 "High" 时,我需要对 MUIAutocomplete 组件执行验证。
我收到一个错误...
Uncaught (in promise) TypeError: branch is not a function
at Condition.fn (index.esm.js:175:1)
at Condition.resolve (index.esm.js:188:1)
at index.esm.js:586:1
at Array.reduce (<anonymous>)
at ObjectSchema.resolve (index.esm.js:586:1)
at ObjectSchema._cast (index.esm.js:1670:1)
at ObjectSchema.cast (index.esm.js:610:1)
at ObjectSchema._cast (index.esm.js:1683:1)
at ObjectSchema.cast (index.esm.js:610:1)
at ObjectSchema._cast (index.esm.js:1683:1)
如果我移除条件验证,一切都正常工作...
requestDetail: yup.object().shape({
riskAssesmentDetail: yup.object().shape({
riskClassification: yup.string().label("Risk Classification").required(),
safetyDetail: yup
.object()
.shape({
investigationType: yup.array().label("Type of Investigation").min(1),
}),
}),
这个错误是关于什么的,如何修复它?
英文:
I have a MUIRadioGroup (options = Low, Medium and High) and a multi-select MUIAutocomplete component on my form.
<MUIRadioGroup
name="requestDetail.riskAssesmentDetail.riskClassification"
label="Risk Classification"
variant="outlined"
size="small"
defaultValue
/>
<MUIAutocomplete
name="requestDetail.riskAssesmentDetail.safetyDetail.investigationType"
label="Type of Investigation"
variant="outlined"
size="small"
multiple
disableCloseOnSelect
options={API_Safety_InvestigationType}
/>
My Schema is...
requestDetail: yup.object().shape({ ...
riskAssesmentDetail: yup.object().shape({
riskClassification: yup
.string()
.label("Risk Classification")
.required()
.typeError("Invalid Selection"),
safetyDetail: yup
.object()
.shape()
.when("riskClassification", {
is: (riskClassification) =>
["Medium", "High"].includes(riskClassification),
then: yup.object({
investigationType: yup
.array()
.label("Type of Investigation")
.min(1),
}),
}),
}),
When radio button is "Medium" or "High, I need to perform validation on the MUIAutocomplete component.
I get an error...
Uncaught (in promise) TypeError: branch is not a function
at Condition.fn (index.esm.js:175:1)
at Condition.resolve (index.esm.js:188:1)
at index.esm.js:586:1
at Array.reduce (<anonymous>)
at ObjectSchema.resolve (index.esm.js:586:1)
at ObjectSchema._cast (index.esm.js:1670:1)
at ObjectSchema.cast (index.esm.js:610:1)
at ObjectSchema._cast (index.esm.js:1683:1)
at ObjectSchema.cast (index.esm.js:610:1)
at ObjectSchema._cast (index.esm.js:1683:1)
If I remove the conditional validation all works...
requestDetail: yup.object().shape({ ...
riskAssesmentDetail: yup.object().shape({
riskClassification: yup.string().label("Risk Classification").required(),
safetyDetail: yup
.object()
.shape({
investigationType: yup.array().label("Type of Investigation").min(1),
}),
}),
What is this error about and how do I fix it?
答案1
得分: 28
我也遇到了这个问题。你的验证条件需要更改,以便在“then”属性上有一个函数。
safetyDetail: yup
.object()
.shape()
.when("riskClassification", {
is: (riskClassification) =>
["Medium", "High"].includes(riskClassification),
then: () => yup.object({
investigationType: yup
.array()
.label("调查类型")
.min(1),
}),
}),
英文:
I just ran into this issue as well. Your when validation needs to change to have a function on the then
property.
safetyDetail: yup
.object()
.shape()
.when("riskClassification", {
is: (riskClassification) =>
["Medium", "High"].includes(riskClassification),
then: () => yup.object({
investigationType: yup
.array()
.label("Type of Investigation")
.min(1),
}),
}),
答案2
得分: 11
I ran into the same issue while doing upgrades. The old version of yup accepted the following.
someField: string().when("someOtherField", {
is: true,
then: string()
.max(5, "Must be 5 characters or less")
.required("Required")
})
The above code was giving me a TypeScript error after upgrading yup. I solved it using the following
someField: string().when("someOtherField", {
is: true,
then: () => string()
.max(5, "Must be 5 characters or less")
.required("Required")
})
英文:
I ran into the same issue while doing upgrades. The old version of yup accepted the following.
someField: string().when("someOtherField", {
is: true,
then: string()
.max(5, "Must be 5 characters or less")
.required("Required")
})
The above code was giving me a TypeScript error after upgrading yup. I solved it using the following
someField: string().when("someOtherField", {
is: true,
then: () => string()
.max(5, "Must be 5 characters or less")
.required("Required")
})
答案3
得分: 2
以下是翻译好的部分:
旧版本(0.3):条件验证的is
、then
和otherwise
函数接受对象作为参数。
新版本(1):then
和otherwise
函数必须返回修改后的模式。它们现在采用空箭头函数() => ... 来返回修改后的模式。
旧版本(0.3):直接在字段上调用验证方法,例如:Yup.string().required()。
新版本(1):验证方法必须通过模式来调用,例如:Yup.string().required() 变为 Yup.string().required()。
旧版本(0.3):使用mixed()
方法在类型未指定时创建模式。
新版本(1):已移除mixed()
方法。在创建模式时必须直接指定类型,例如:Yup.string()。
旧版本(0.3):validate()
方法直接返回验证错误(如果存在),否则返回undefined。
新版本(1):validate()
方法返回一个Promise。必须使用await或.then()来获取结果。
旧版本(0.3):isValid()
方法直接返回true(如果验证成功),否则返回false。
新版本(1):isValid()
方法返回一个Promise。必须使用await或.then()来获取结果。
旧版本(0.3):使用nullable()
和notRequired()
方法来指定字段可以为null或不是必需的。
新版本(1):这些方法已被移除。要允许字段为null或不是必需的,可以在字段后面不调用任何验证方法(例如:Yup.string().nullable() 现在变成 Yup.string())。
新版本(1):oneOf()
方法现在用于验证值是否属于给定的集合。例如:Yup.string().oneOf(['value1', 'value2']).
这些变化反映了Yup的两个版本之间的一些重要差异。
英文:
for those who want a real and complex example :
Here is before upgrade version :
import * as Yup from 'yup';
interface optionsType {
id: string;
label: string;
value: string;
}
const formEpischema = Yup.object().shape(
{
attestationType: Yup.object({}).shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
activityType: Yup.object({}).when('attestationType', {
is: (attestationType: optionsType) =>
attestationType.label !== 'Standard',
then: Yup.object({}).shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
otherwise: Yup.object({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
})
}),
shoesType: Yup.array().when(['helmetType', 'otherEquipement'], {
is: (helmetType: optionsType[], otherEquipement: string) =>
!helmetType?.length && !otherEquipement,
then: Yup.array()
.of(
Yup.object().shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
})
)
.min(1)
.required()
}),
shoesCriteria: Yup.object({}).shape({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
}),
shoesSize: Yup.number().min(10).max(55),
helmetType: Yup.array().when(['shoesType', 'otherEquipement'], {
is: (shoesType: optionsType[], otherEquipement: string) =>
!shoesType?.length && !otherEquipement,
then: Yup.array()
.of(
Yup.object().shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
})
)
.min(1)
.required()
}),
otherEquipement: Yup.string()
.min(4)
.when(['shoesType', 'helmetType'], {
is: (shoesType: optionsType[], helmetType: optionsType[]) =>
!shoesType?.length && !helmetType?.length,
then: Yup.string().min(4).required()
}),
isCefri: Yup.boolean().oneOf([true, false]),
dosimeterType: Yup.object({}).when('isCefri', {
is: true,
then: Yup.object({}).shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
otherwise: Yup.object({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
})
}),
dosimeterRef: Yup.string().when('isCefri', {
is: true,
then: Yup.string().min(7).max(7).required(),
otherwise: Yup.string()
})
},
[
['shoesType', 'helmetType'],
['shoesType', 'otherEquipement'],
['helmetType', 'otherEquipement']
]
);
export default formEpischema;
Here is now :
import * as Yup from 'yup';
interface optionsType {
id: string;
label: string;
value: string;
}
const formEpischema = Yup.object().shape({
attestationType: Yup.object({ // change is here 👈
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
activityType: Yup.object().when('attestationType', {
is: (attestationType: optionsType) => attestationType.label !== 'Standard',
then: () => // change is here 👈
Yup.object({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
otherwise: () => // change is here 👈
Yup.object({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
})
}),
shoesType: Yup.array().when(['helmetType', 'otherEquipement'], {
is: (helmetType: optionsType[], otherEquipement: string) => !helmetType?.length && !otherEquipement,
then: () => // change is here 👈
Yup.array()
.of(
Yup.object().shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
})
)
.min(1)
.required()
}),
shoesCriteria: Yup.object({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
}),
shoesSize: Yup.number().min(10).max(55),
helmetType: Yup.array().when(['shoesType', 'otherEquipement'], {
is: (shoesType: optionsType[], otherEquipement: string) => !shoesType?.length && !otherEquipement,
then: () =>
Yup.array()
.of(
Yup.object().shape({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
})
)
.min(1)
.required()
}),
otherEquipement: Yup.string().min(4).when(['shoesType', 'helmetType'], {
is: (shoesType: optionsType[], helmetType: optionsType[]) => !shoesType?.length && !helmetType?.length,
then: () => Yup.string().min(4).required()
}),
isCefri: Yup.boolean().oneOf([true, false]),
dosimeterType: Yup.object().when('isCefri', {
is: true,
then: () =>
Yup.object({
id: Yup.string().required(),
label: Yup.string().required(),
value: Yup.string().required()
}),
otherwise: () =>
Yup.object({
id: Yup.string(),
label: Yup.string(),
value: Yup.string()
})
}),
dosimeterRef: Yup.string().when('isCefri', {
is: true,
then: (schema) => schema.min(7).max(7).required(),
otherwise: () => Yup.string()
})
},
[
['shoesType', 'helmetType'],
['shoesType', 'otherEquipement'],
['helmetType', 'otherEquipement']
]
);
export default formEpischema;
Old version (0.3): The is
, then
, and otherwise
functions of conditional validations accepted objects as arguments.
New version (1): The then and otherwise functions must return a modified schema. They now take empty arrow functions () => ... to return the modified schema.
Old version (0.3): Validation methods such as required()
, min(), max(), etc. were called directly on the fields (for example: Yup.string().required()).
New version (1): Validation methods must be called via the schema (for example: Yup.string().required() becomes Yup.string().required()).
Old version (0.3): The mixed()
method was used to create a schema when the type was not specified.
New version (1): The mixed()
method has been removed. You must specify the type directly when creating the schema (for example: Yup.string()).
Old version (0.3): The validate()
method directly returned validation errors if they existed, otherwise returned undefined.
New version (1): The validate() method returns a promise. You must use await or .then() to get the results.
Old version (0.3): The isValid()
method directly returned true if the validation was successful, otherwise returned false.
New version (1): The isValid() method returns a promise. You must use await or .then() to get the results.
Old version (0.3): The nullable()
and notRequired(
) methods were used to specify that a field could be null or not required.
New version (1): These methods have been removed. To allow a field to be null or not required, you can simply not call any validation method after the field (eg: Yup.string().nullable() just becomes Yup.string()).
New version (1): The oneOf()
method is now used to validate that a value is part of a given set. For example: Yup.string().oneOf(['value1', 'value2']).
These changes reflect some of the important differences between the two versions of Yup.
答案4
得分: 0
When
validation now has a new syntax:
let schema = object({
id: yup.number().notRequired(),
thumbnail: yup.mixed().when('id', {
is: (id: number | undefined) => id !== undefined,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
});
Notice the then:
and otherwise:
are functions with schema
as a parameter.
More examples from the documentation
英文:
When
validation now has a new syntax:
let schema = object({
id: yup.number().notRequired(),
thumbnail: yup.mixed().when('id', {
is: (id: number | undefined) => id !== undefined,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
});
Notice the then:
and otherwise:
are functions with schema
as a parameter.
More examples from the documentation
答案5
得分: 0
我也遇到了同样的问题,在JavaScript中使用了Yup条件验证模式,使用了`when`条件。
像这样 // JAVASCRIPT VERSION
export const CreateTicketValidationSchema = Yup.object({
// 为礼貌电话制作的额外验证
logCourtesyCall: Yup.boolean(),
customer: Yup.string().when("logCourtesyCall", {
is: (value) => value === false,
then: Yup.string().required("字段是必需的").max(250, "超出最大字符限制"),
otherwise: Yup.string().max(250, "超出最大字符限制"),
}),
accountManager: Yup.string().when("logCourtesyCall", {
is: (value) => value === false,
then: Yup.string().required("字段是必需的").max(50, "超出最大字符限制"),
otherwise: Yup.string().max(50, "超出最大字符限制"),
}),
});
// 如果你在Yup的TypeScript版本中遇到问题,可以使用更新的代码
export const forgetPasswordValidation = Yup.object().shape({
emailStatus: Yup.bool(),
otpStatus: Yup.bool(),
email: Yup.string().when('emailStatus', {
is: false,
then: () =>
Yup.string().email('无效的电子邮件地址').required('请输入电子邮件地址'),
}),
otp: Yup.string().when('emailStatus', {
is: true,
then: () => Yup.string().min(6).max(6).required('请输入OTP'),
}),
newPassword: Yup.string().when('otpStatus', {
is: true,
then: () =>
Yup.string()
.required('需要新密码')
.min(8, '密码必须至少为8个字符')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/,
'密码必须包含至少一个小写字母、一个大写字母、一个数字和一个特殊字符',
),
}),
confirmPassword: Yup.string().when('otpStatus', {
is: true,
then: () =>
Yup.string().oneOf([Yup.ref('newPassword')], '两个密码必须相同'),
}),
});
希望这能帮到你。 :)
英文:
I too was facing same problem where I used Yup conditional validation schema in Javascript with when
condition,
Like this // JAVASCRIPT VERSION
export const CreateTicketValidationSchema = Yup.object({
// Extra validation for courtesy call making
logCourtesyCall: Yup.boolean(),
customer: Yup.string().when("logCourtesyCall", {
is: (value) => value === false,
then: Yup.string().required("Field is required").max(250, "Maximum character limit exceed"),
otherwise: Yup.string().max(250, "Maximum character limit exceed"),
}),
accountManager: Yup.string().when("logCourtesyCall", {
is: (value) => value === false,
then: Yup.string().required("Field is required").max(50, "Maximum character limit exceed"),
otherwise: Yup.string().max(50, "Maximum character limit exceed"),
}),
});
// UPDATED CODE IF YOU ARE FACING ISSUE IN TYPESCRIPT VERSION OF YUP
export const forgetPasswordValidation = Yup.object().shape({
emailStatus: Yup.bool(),
otpStatus: Yup.bool(),
email: Yup.string().when('emailStatus', {
is: false,
then: () =>
Yup.string().email('Invalid email address').required('Please enter email address'),
}),
otp: Yup.string().when('emailStatus', {
is: true,
then: () => Yup.string().min(6).max(6).required('Please enter OTP'),
}),
newPassword: Yup.string().when('otpStatus', {
is: true,
then: () =>
Yup.string()
.required('New password is required')
.min(8, 'Password must be at least 8 characters long')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/,
'Password must contain at least one lowercase letter, one uppercase letter, one number, and one special character',
),
}),
confirmPassword: Yup.string().when('otpStatus', {
is: true,
then: () =>
Yup.string().oneOf([Yup.ref('newPassword')], 'Both password need to be the same'),
}),
});
Hope this will help you.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论