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

如何基于外部Checkbox状态用Yup.test()实现表单字段条件校验?

解决方案:基于Checkbox状态的条件必填校验(React Hook Form + Yup)

方法一:使用Yup when() 实现条件校验(推荐)

Yup的when()方法专门处理字段间的条件依赖,比test()更简洁直观,完全适配你的需求:

import { useForm, useWatch } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
import { useMemo } from 'react';

export default function FileUploadForm() {
  const { register, handleSubmit, formState: { errors }, control } = useForm({
    defaultValues: {
      isUploadRequired: false,
      tenderReturnReportPath: null
    }
  });

  // 监听Checkbox状态变化
  const isUploadRequired = useWatch({ control, name: 'isUploadRequired' });

  // 定义条件校验Schema
  const validationSchema = Yup.object().shape({
    isUploadRequired: Yup.boolean(),
    tenderReturnReportPath: Yup.mixed()
      .when('isUploadRequired', {
        is: true, // 当Checkbox勾选时
        then: (schema) => schema.required('请上传文件'), // 字段设为必填
        otherwise: (schema) => schema.notRequired() // 未勾选时跳过校验
      })
  });

  // 缓存resolver,避免状态变化时重复生成
  const resolver = useMemo(() => yupResolver(validationSchema), [isUploadRequired]);

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <input
          type="checkbox"
          {...register('isUploadRequired')}
          id="upload-check"
        />
        <label htmlFor="upload-check">需要上传文件</label>
      </div>

      <div>
        <input
          type="file"
          {...register('tenderReturnReportPath')}
          disabled={!isUploadRequired}
          id="file-upload"
        />
        {errors.tenderReturnReportPath && <p className="error">{errors.tenderReturnReportPath.message}</p>}
      </div>

      <button type="submit">提交表单</button>
    </form>
  );
}

方法二:使用Yup test() 自定义校验逻辑

如果需要更复杂的自定义规则,可以用test()方法,通过this.parent访问表单内的Checkbox状态:

const validationSchema = Yup.object().shape({
  isUploadRequired: Yup.boolean(),
  tenderReturnReportPath: Yup.mixed()
    .test(
      'required-if-checked', // 校验规则唯一标识
      '请上传文件', // 错误提示文本
      function(value) {
        // 通过this.parent获取Checkbox的状态
        const shouldRequire = this.parent.isUploadRequired;
        if (shouldRequire) {
          // 勾选时校验文件是否存在
          return value !== null && value !== undefined;
        }
        // 未勾选时直接通过校验
        return true;
      }
    )
});

方法三:直接使用React Hook Form内置校验(无需Yup)

如果校验逻辑简单,完全可以跳过Yup,直接在register中定义validate规则,代码更轻量化:

<input
  type="file"
  {...register('tenderReturnReportPath', {
    validate: (value) => {
      if (isUploadRequired && !value) {
        return '请上传文件';
      }
      return true;
    }
  })}
  disabled={!isUploadRequired}
  id="file-upload"
/>

关键注意事项

  • 用useWatch监听Checkbox状态,配合useMemo缓存yupResolver,确保状态变化时校验规则同步更新,避免不必要的重渲染。
  • 给上传字段添加disabled={!isUploadRequired},React Hook Form会自动跳过禁用字段的校验,和规则形成双重保障。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:27:25