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

Yup的when方法未按预期生效,勾选复选框后关联字段未触发必填校验

Yup when() 条件校验不生效的解决方案

问题原因

  • 对Yup条件校验的生效逻辑理解偏差:when()规则是在校验执行的瞬间才会读取依赖字段的值动态判断是否生效,schema实例本身是不可变的,在useEffect中打印schema.fields看不到规则变化属于正常情况,不代表规则未生效。
  • 缺少校验触发与错误展示逻辑:当前代码未添加提交逻辑、错误提示展示,也没有主动触发校验的操作,无法感知到required规则的生效。mode:all配置仅会在字段值变化、失焦时触发对应字段的校验,初始加载不会自动校验全部字段。
  • 非最优实践:schema定义放在组件内部会导致每次组件重渲染都生成新的schema实例,存在冗余开销。
  • 写法兼容风险:部分when回调直接返回新的yup.string().required()属于冗余写法,可能丢失原有字段配置上下文,建议统一用上下文修改写法。

修复后的完整代码

import "./styles.css";
import * as yup from "yup";
import { FormProvider, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import React from "react";

// schema移到组件外部,避免重复生成实例
const schema = yup.object({
  isRequired: yup.bool(),
  firstName: yup.string().when("isRequired", (_, schema) => {
    return schema.required("请填写名");
  }),
  lastName: yup.string().when("isRequired", (_, schema) => {
    return schema.required("请填写姓");
  }),
  contact: yup.string().when("isRequired", {
    is: true,
    then: (schema) => schema.required("请填写联系方式")
  })
});

export default function App() {
  const methods = useForm({
    mode: "all",
    defaultValues: {
      isRequired: true,
      firstName: "",
      lastName: "",
      contact: ""
    },
    resolver: yupResolver(schema),
    shouldUnregister: true
  });

  const { register, formState: { errors }, handleSubmit } = methods;

  const onSubmit = (data) => {
    console.log("提交数据", data);
  };

  return (
    <FormProvider {...methods}>
      <form autoComplete="off" noValidate onSubmit={handleSubmit(onSubmit)}>
        <div>
          <input type="checkbox" {...register("isRequired")} />
          <label>开启必填校验</label>
        </div>
        <div>
          <input {...register("firstName")} placeholder="名" />
          {errors.firstName && <span>{errors.firstName.message}</span>}
        </div>
        <div>
          <input {...register("lastName")} placeholder="姓" />
          {errors.lastName && <span>{errors.lastName.message}</span>}
        </div>
        <div>
          <input {...register("contact")} placeholder="联系方式" />
          {errors.contact && <span>{errors.contact.message}</span>}
        </div>
        <button type="submit">提交表单</button>
      </form>
    </FormProvider>
  );
}

验证方式

修复后勾选复选框,直接点击提交按钮,即可看到三个输入框对应的必填错误提示;取消勾选后提交,不会触发必填校验。

内容的提问来源于stack exchange,提问作者Izabela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:54:04