React-Hook-Form中Yup对象数组的条件验证问题排查
Yup动态表单条件验证问题修复
问题分析
你当前的代码中,子Schema(如blogPostSchema)的字段本身被设置为必填,即使父级数组字段通过when设置了notRequired,只要表单中存在该数组字段(哪怕是空数组或未填全字段),子Schema的必填规则就会触发验证。另外你已经给contentType设置了required,所以contentType为undefined的情况不会出现,可以去掉这个判断条件。
解决方案
需要调整两个核心点:
- 当对应
contentType未选中时,允许数组字段为undefined或null,且不触发子Schema的验证 - 仅在对应
contentType选中时,要求数组字段必须存在且包含符合子Schema的元素
修改后的完整代码如下:
import * as yup from "yup"; // 子Schema保持原有字段规则,但仅在父级数组被要求时生效 const blogPostSchema = yup.object().shape({ blogPostBody: yup.string().required("Body is required"), blogPostTags: yup.string().required("Tags are required"), }); const productListingSchema = yup.object().shape({ productName: yup.string().required("Product Name is required"), price: yup .number() .required("Price is required") .typeError("Price must be a number") .positive("Price must be a positive number") .min(1, "Price must be at least 1"), category: yup.string().required("Category is required"), }); const eventSchema = yup.object().shape({ eventDate: yup .date() .required("Event Date is required") .typeError("Please enter a valid date"), location: yup.string().required("Location is required"), description: yup.string().required("Description is required"), }); export const schema = yup.object({ contentType: yup.string().required("Content type is required"), title: yup.string().required("Title is required"), author: yup.string().required("Author is required"), blogPosts: yup .array() .of(blogPostSchema) // 允许字段为null/undefined,不需要时跳过验证 .nullable() .when("contentType", { is: "Blog Post", // 选中Blog Post时,数组必须非空且元素符合规则 then: (schema) => schema.required("Blog posts are required").min(1, "At least one blog post is required"), // 未选中时,允许字段为null/undefined,不做验证 otherwise: (schema) => schema.notRequired().nullable() }), productListings: yup .array() .of(productListingSchema) .nullable() .when("contentType", { is: "Product Listing", then: (schema) => schema.required("Product listings are required").min(1, "At least one product listing is required"), otherwise: (schema) => schema.notRequired().nullable() }), events: yup .array() .of(eventSchema) .nullable() .when("contentType", { is: "Event", then: (schema) => schema.required("Events are required").min(1, "At least one event is required"), otherwise: (schema) => schema.notRequired().nullable() }), }).required();
额外优化建议
- 配合React-Hook-Form的
watch方法,在切换contentType时清空不需要的数组字段,避免表单残留旧数据导致的验证异常 - 如果需要支持
contentType未选择的状态(即去掉contentType的required),可以恢复value === undefined的判断逻辑,同步调整对应数组字段的条件验证规则
内容的提问来源于stack exchange,提问作者Danish Irfan
相关产品推荐
相关产品推荐

