React Hook Form V7 如何设置仅所有字段为空时触发的联合校验规则
方案说明
React Hook Form V7 本身就内置了该需求的实现能力,不需要额外维护自定义submitError状态,所有校验逻辑和错误状态都可以交给RHF统一管理。
你可以根据是否使用第三方校验库,选择以下两种实现方式:
方案1:纯RHF原生实现(无需引入第三方校验库)
直接在useForm的全局校验配置中定义规则,错误会自动挂载到formState.errors.root下:
import { useForm, Controller } from 'react-hook-form' import TextField from '@mui/material/TextField' const Demo = () => { const { control, handleSubmit, formState: { errors } } = useForm({ defaultValues: { test1: '', test2: '' }, // 全局自定义校验规则 validate: (values) => { if (!values.test1.trim() && !values.test2.trim()) { return { emptyError: 'test1和test2至少需要填写一个' } } } }) const onSubmit = (data) => { // 能进入这里说明已经通过校验,直接执行提交逻辑即可 console.log(data) } return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller render={({ field }) => <TextField {...field} />} name="test1" control={control} // 不需要单独设置required规则 /> <Controller render={({ field }) => <TextField {...field} />} name="test2" control={control} // 不需要单独设置required规则 /> {/* 直接读取RHF管理的全局错误即可 */} {errors.root?.emptyError && <span>{errors.root.emptyError}</span>} <input type="submit" /> </form> ) }
方案2:配合第三方校验库实现(以Zod为例)
如果你项目中已经在使用Zod/Yup等校验库配合RHF的resolver使用,可以直接通过校验库的全局校验规则实现,逻辑更聚合:
import { useForm, Controller } from 'react-hook-form' import { z } from 'zod' import { zodResolver } from '@hookform/resolvers/zod' import TextField from '@mui/material/TextField' // 定义校验schema const formSchema = z.object({ test1: z.string().optional(), test2: z.string().optional() }).refine((val) => !!val.test1.trim() || !!val.test2.trim(), { message: 'test1和test2至少需要填写一个', path: ['root'] }) const Demo = () => { const { control, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(formSchema), defaultValues: { test1: '', test2: '' } }) const onSubmit = (data) => { console.log(data) } return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller render={({ field }) => <TextField {...field} />} name="test1" control={control} /> <Controller render={({ field }) => <TextField {...field} />} name="test2" control={control} /> {errors.root?.message && <span>{errors.root.message}</span>} <input type="submit" /> </form> ) }
补充说明
RHF默认会在handleSubmit触发时自动执行所有配置的校验规则,校验通过才会进入你传入的onSubmit回调,完全不需要你自己在校验不通过的分支做逻辑拦截,也不需要额外维护错误状态。如果你需要实现输入过程中实时校验,只需要在useForm的配置中添加mode: 'onChange'即可,其他逻辑不需要调整。
内容的提问来源于stack exchange,提问作者Moon
相关产品推荐
相关产品推荐

