You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:45:11