我想在 formik 中使用 yup 验证我的表单。假设我有 4 个字段 A、B、C、D,它们都是字符串。如果我希望至少有一个字段不为空,那么我应该如何编写验证模式,那么这是一种有效的形式?提前致谢!
使用 Yup 时,如果所有正常功能都失败了,您可以使用
.test
功能,记录在此处 - https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function -架构
mixed.test(name: string, message: string | function, test: function): Schema
向验证链添加测试功能。在投射任何对象后运行测试。许多类型都内置了一些测试,但您可以轻松创建自定义测试。为了允许异步自定义验证,所有(或没有)测试都是异步运行的。这样做的结果是无法保证测试执行顺序。
对于您的实施,您需要为 4 个字段中的每一个编写一个“测试”,以确保这 4 个字段中的一个不为空。
field1: yup
.string()
.test(
'oneOfRequired',
'One of Field1, Field2, Field3 or Field4 must be entered',
function(item) {
return (this.parent.field1 || this.parent.field2 || this.parent.field3 || this.parent.field4)
}
),
field2: yup
.string()
.test(
'oneOfRequired',
'One of Field1, Field2, Field3 or Field4 must be entered',
function(item) {
return (this.parent.field1 || this.parent.field2 || this.parent.field3 || this.parent.field4)
}
),
等...
请注意,在这种情况下,我没有使用箭头功能。这是因为要使用“this”上下文,您必须使用此语法,Yup 文档中提到了这一点。
如果您不想将验证添加到每个字段,而是为这些事情设置一个“全局”错误处理程序,还有另一种可能性。
你会做这样的事情:
const schema = yup.object().shape({
field1: yup.string().required(),
field2: yup.string().required(),
field3: yup.string().required(),
field4: yup.string().required(),
}).test('yourTestCondition', function (value) {
// your global test code...
})
您正在搜索的内容有一个解决方案。您可以只为父元素编写一个测试,而不是为每个元素编写一个测试。模拟全局错误。
yup.object({
field1: yup.string(),
field2: yup.string(),
field3: yup.string(),
field4: yup.string(),
})
.test('global-ok',
'you do not fulfill the requirements',
function (value) {
return CONDITION OVER THE CHILDREN;
})
比如不想写一系列必填元素的错误,只给出一种全局错误。你可以:
yup.object({
username: yup.string().required(),
password: yup.string().required(),
email: yup.string().required().test(verify_email),
})
.test('global-ok',
'The data is not correct',
function (value) {
return username && password && email;
})
这是一个把事情放在上下文中的例子
考虑只有当他/她来自美国并且超过 10 年时才需要学生姓名,对于这种情况,这就是我们可以编写 yup 配置的方式。
注意:多个字段用于验证
const formSchema = yup.object({
age: yup.number(),
country: yup.string(),
studentName: yup.string().when(['age', 'country'], {
is: (age: string, country: string) => {
if (age > 10) {
return true // validate and check next condition
}
if (country === 'USA') {
return true // validate and go to then function
} else return false // for all other cases studentName is not required
},
then: (schema) =>
schema
.required("Student name is required")
})
})
email: Yup.string()
.when([‘, 'showEmail’, ’anotherField’], {
is: (showEmail, anotherField) => {
return (showEmail && anotherField);
},
then: Yup.string().required('Must enter email address')
}),
多个字段也可以用于验证。 处理多个参数的最简单方法
如果你更喜欢 ES6 并且想使用 arrow functions,Jamie answer answer 的修改版本是这样的:
field1: yup
.string()
.test(
'oneOfRequired',
'One of Field1, Field2, Field3 or Field4 must be entered',
(item,testContext)=>{
return (testContext.parent.field1 || testContext.parent.field2 || testContext.parent.field3 || testContext.parent.field4)
}
),
field2: yup
.string()
.test(
'oneOfRequired',
'One of Field1, Field2, Field3 or Field4 must be entered',
(item,testContext)=> {
return (testContext.parent.field1 || testContext.parent.field2 || testContext.parent.field3 || testContext.parent.field4)
}
),
有关详细信息,官方文档.
lazy(value => {
switch (typeof value) {
case 'array':
return array().of(string()).nullable();
case 'string':
return string().nullable();
default:
return array().of(string()).nullable();
}
}),