我的项目有 Yup 0.32.11 和 Formik 2.2.9,我正在尝试使用 Yup.mixed().when(...) 方法来控制基于同级字段的验证消息。传递到 when(...) 方法的同级字段的值始终是未定义的,我不明白为什么。
具体来说,我希望我的“州”字段验证所需的错误消息在“国家/地区”字段为“美国”/空时显示“需要州”,并在“国家/地区”字段为其他任何内容时显示“需要省”。
说明问题的示例代码和框,包括下面的所有片段,位于此处。
表格的部分定义:
<Formik
initialValues={{
name: "",
mailingAddress: {
line: "",
city: "",
state: "",
country: ""
}
}}
validationSchema={ValidationSchema}
...
>
以下是我尝试过的验证模式的 4 种不同变体,所有这些变体的行为就好像同级字段(国家/地区)未定义:
const ValidationSchema = Yup.object({
name: Yup.string().required(),
mailingAddress: Yup.object({
line: Yup.string().required(),
city: Yup.string().required(),
country: Yup.string().required(),
//=== attempt 1 ... always returns province ===
state: Yup.mixed().when("mailingAddress.country", {
is: "US",
then: Yup.string().trim().required(stateMsg),
otherwise: Yup.string().trim().required(provinceMsg)
})
//=== attempt 2 ... always returns state ===
// state: Yup.mixed().when("mailingAddress.country", {
// is: (value: string) => (value === undefined || value === "" || value === "US"),
// then: Yup.string().trim().required(stateMsg),
// otherwise: Yup.string().trim().required(provinceMsg)
// })
//=== attempt 3 ... always returns state ===
// state: Yup.mixed().when("mailingAddress.country", {
// is: (value: string) => {
// return (value === undefined || value === "" || value === "US");
// },
// then: Yup.string().trim().required(stateMsg),
// otherwise: Yup.string().trim().required(provinceMsg)
// })
//=== attempt 4 ... always returns state ===
// state: Yup.mixed().when("mailingAddress.country", (value, context) => {
// if (value === undefined || value === "" || value === "US") {
// return Yup.string().trim().required(stateMsg);
// } else {
// return Yup.string().trim().required(provinceMsg);
// }
// })
//=== the end ===
})
});
这里是使用 test 而不是 when 的解决方法,但不幸的是,它需要多次传递数据,因此仍然希望得到更好的答案。
state: Yup.string().trim()
.test("mailingAddressState-US", stateMsg, (value, context) => {
let state = value || "";
let country = context.parent.country || "";
return (country !== "US" || state > "");
})
.test("mailingAddressState-nonUS", provinceMsg, (value, context) => {
let state = value || "";
let country = context.parent.country || "";
return (country === "US" || state > "");
}),
我最近在 Yup 验证中遇到了类似的问题,其中我在
.when()
中引用的字段位于上层(不在父级甚至更高层中),这似乎就是引用该字段时未定义的原因。但使用.when('$values.yourFieldInUpperLevel', {...})
它完美地解决了我的问题。希望这可以帮助其他人,甚至我自己:))
state: Yup.mixed().when("$values.mailingAddress.country", {
is: "US",
then: Yup.string().trim().required(stateMsg),
otherwise: Yup.string().trim().required(provinceMsg)
})