Yup测试返回true时react-hook-form的multiCheckbox错误未清除问题
问题根因
react-hook-form 默认仅对字段的直接修改触发校验,你修改multiCheckbox下的option1/option2属于嵌套子字段的修改,默认不会触发父字段multiCheckbox的重校验,所以即使Yup的test函数返回true,multiCheckbox对应的错误状态也不会自动更新,导致错误提示一直保留。一级字段singleCheckbox修改时会直接触发自身校验,所以表现正常。你观测到的再次点击提交错误消失,是因为提交时会执行全量校验,此时multiCheckbox的校验会被触发,错误状态就正常更新了。你之前调整revalidation配置不生效,本质是因为该配置只控制已触发过校验的字段自身的重校验逻辑,不会处理父子字段的校验联动。
可落地解决方案
方案1:手动触发父字段校验(改造成本最低)
在每个嵌套复选框的onChange事件末尾,调用react-hook-form提供的trigger方法主动触发multiCheckbox的校验即可:
import { useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; const { trigger, setValue, getValues } = useForm({ resolver: yupResolver(yupSchema), defaultValues }); // 嵌套复选框的change回调示例 const handleOptionChange = (optionKey) => { // 原有更新字段的逻辑保持不变 setValue(`multiCheckbox.${optionKey}`, !getValues(`multiCheckbox.${optionKey}`)); // 新增一行主动触发父字段校验 trigger("multiCheckbox"); };
不需要修改原有数据结构和校验规则,新增一行代码即可解决问题。
方案2:调整多选项存储结构(长期维护更友好)
把multiCheckbox从嵌套对象改为数组存储选中的选项值,直接用Yup的数组校验规则,天然不存在嵌套字段校验联动问题:
// 调整默认值结构 const defaultValues = { companyName: "", singleCheckbox: false, multiCheckbox: [] // 选中的选项会存入数组,比如选中option1时数组值为["option1"] }; // 调整对应的Yup校验规则 const yupSchema = yup.object().shape({ companyName: yup.string().required("Company name is required"), singleCheckbox: yup.boolean().test("singleCheckbox", "Required", (val) => val), multiCheckbox: yup.array().min(1, "At least one of the checkbox is required") });
这种方式更符合多选项表单的常规设计逻辑,后续扩展选项也不需要修改校验规则。
方案3:开启全量校验触发(仅适合小表单)
如果表单字段数量少,可以在useForm配置中设置mode: "all",每次任意字段修改都会触发全量校验,也能解决嵌套字段的校验问题,但会增加不必要的性能开销,不推荐字段多的表单使用。
内容的提问来源于stack exchange,提问作者Fethi Wap
相关产品推荐
相关产品推荐

