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
相关产品推荐
相关产品推荐

