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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:06:01