React+Formik+Yup:动态数组为空/未定义时跳过验证
解决方案
问题分析
你的数组包含3个未定义的空元素和1个有效对象,当前Yup会对数组中所有元素(包括空元素)执行校验,导致空元素触发必填项报错。需要实现仅对已定义且非空的元素执行校验,空元素直接跳过。
实现代码
使用Yup.lazy()动态生成校验规则,根据数组元素的实际值决定是否启用校验:
translator_services: Yup.array().of( Yup.lazy(item => { // 若元素未定义或为空对象,返回无校验规则的schema if (!item || Object.keys(item).length === 0) { return Yup.mixed(); } // 若元素为有效对象,应用原有的字段校验规则 return Yup.object().shape({ translator_category_id: Yup.string().required("Required"), translator_category_description: Yup.string().nullable().required("Description is required."), translator_category_type_id: Yup.array().nullable().min(1, "Select at least one service type"), }); }) ),
原理说明
Yup.lazy()会遍历数组的每个元素,根据元素的实际值动态返回对应的校验schema- 当元素是
undefined(即数组中的empty项)或空对象时,返回Yup.mixed(),这个类型的schema不会执行任何校验逻辑,直接跳过 - 当元素是有效对象时,返回你原来定义的对象校验规则,正常校验字段的必填性和格式
另一种实现方式(基于条件校验)
如果不想用lazy,也可以给每个字段添加when条件,判断当前元素是否存在后再启用校验:
translator_services: Yup.array().of( Yup.object().shape({ translator_category_id: Yup.string().when("$self", { is: (obj) => obj && Object.keys(obj).length > 0, then: (schema) => schema.required("Required"), otherwise: (schema) => schema.optional() }), translator_category_description: Yup.string().nullable().when("$self", { is: (obj) => obj && Object.keys(obj).length > 0, then: (schema) => schema.required("Description is required."), otherwise: (schema) => schema.optional() }), translator_category_type_id: Yup.array().nullable().when("$self", { is: (obj) => obj && Object.keys(obj).length > 0, then: (schema) => schema.min(1, "Select at least one service type"), otherwise: (schema) => schema.optional() }) }) ),
这种方式通过$self引用当前元素对象,仅当对象存在且非空时,才启用字段的校验规则。
内容的提问来源于stack exchange,提问作者Gajanan Pawaskar
相关产品推荐
相关产品推荐

