配置Yup校验规则:实现3个输入框至少填2个且仅提示文本变红
解决方案
要实现「3个输入框至少填写2个」的Yup校验,并且仅让提示文本变红,你可以按照以下步骤配置:
1. 导入依赖
确保你已经安装了 yup 和 @hookform/resolvers,然后在组件中导入:
import * as Yup from 'yup'; import { yupResolver } from '@hookform/resolvers/yup'; import { useForm } from 'react-hook-form';
2. 定义Yup校验规则
通过 Yup.object().test() 编写自定义校验逻辑,将错误信息绑定到你原代码中使用的 extendDevice 路径上,确保样式判断生效:
const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver( Yup.object().shape({ // 三个字段仅做类型兼容,不单独校验 serialNumber: Yup.string().nullable(), businessNumber: Yup.string().nullable(), pinNumber: Yup.number().nullable(), }).test( 'at-least-two-fields', '', function(value) { const { serialNumber, businessNumber, pinNumber } = value; // 统计已填写的字段数量(排除空字符串、null、undefined) const filledCount = [serialNumber, businessNumber, pinNumber].filter( item => item !== null && item !== '' && item !== undefined ).length; // 未满足条件时抛出错误,指定错误路径为extendDevice if (filledCount < 2) { return this.createError({ path: 'extendDevice', message: t('common:errors.atLeastTwoFields'), }); } return true; } ) ), defaultValues: { serialNumber: '', businessNumber: '', pinNumber: null, }, });
3. 调整表单代码
- 移除
Paper组件上的{...register('extendDevice')}(不需要注册这个字段,错误通过Yup手动绑定) - 将表单的提交逻辑绑定到
form标签的onSubmit属性,而非按钮的onClick:
<form onSubmit={handleSubmit(onSubmit)}> {!loading ? ( <Paper title={t('common:cardTitles.extendDevice')}> {/* 原头部提示区域保持不变 */} <div className="flex md:flex-row flex-col justify-center items-center md:justify-between border-b-[1px] md:pb-6 pb-[17px]"> <h3 className="font-bold subheading">{t('common:deviceData')}</h3> <div className="flex flex-row gap-1"> <ErrorIcon className={`text-${errors.extendDevice ? 'red-600' : '#80858F'} w-6`} /> <p className={mergeClasses( 'md:text-sm text-xs', errors.extendDevice ? 'text-red-600' : 'text-[#80858F]', )} > {t('common:errors.atLeastTwoFields')} </p> </div> </div> {/* 输入框区域保持不变,仅保留register注册 */} <div className="md:pt-6 pt-[17px] grid md:grid-cols-2 gap-4"> <TextInput {...register('serialNumber')} label={t('common:labels.serialNumber')} name="serialNumber" placeholder={t('common:placeholders.typeSerialNumber')} /> <TextInput {...register('businessNumber')} label={t('common:labels.businessNumber')} name="business-number" placeholder={t('common:placeholders.typeBusinessNumber')} /> </div> <div className="pt-4"> <NumberInput {...register('pinNumber')} label={t('common:labels.pin')} name="pin-number" placeholder={t('common:placeholders.typePinNumber')} /> </div> {/* 按钮移除onClick,保留type="submit" */} <div className="flex w-full justify-end pt-4"> <Button className="py-3.5 px-6 bg-[#336BB3] text-white md:w-[115px] w-full" label={t('common:labels.verify')} type="submit" /> </div> </Paper> ) : ( <VerificationInProgress /> )} </form>
关键说明
- 自定义校验通过
this.createError指定错误路径为extendDevice,完美匹配你原代码中errors.extendDevice的样式判断逻辑 - 三个输入框仅做类型兼容,不添加单独的必填校验,避免输入框自身显示错误状态
- 提交表单时,React Hook Form 会自动触发整个Schema的校验,未满足条件时提示文本自动变红
内容的提问来源于stack exchange,提问作者Jan Bo
相关产品推荐
相关产品推荐

