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

如何让react-hook-form多步骤表单的yup.test仅触发一次校验?

Yup异步校验重复执行问题原因及解决方案

问题原因

该问题确实和trigger方法的使用,以及react-hook-form配合yup的默认校验逻辑有关,核心原因如下:

  • 你在三个节点都主动/被动触发了包含email/phone字段的校验规则
    • 第一步点击下一步:主动调用trigger(['email', 'password', 'passwordConfirm']),触发email的校验
    • 第二步点击下一步:主动调用trigger(['firstname', 'lastname', 'middlename', 'typeClient', 'phone']),默认配置下YupResolver会执行全量schema校验,哪怕你只指定触发部分字段,yup也会跑完所有字段的校验逻辑,所以这一步除了当前步骤的字段,email的校验也会被重新执行
    • 最后点击提交按钮:react-hook-form的handleSubmit方法默认会在提交前触发全表单所有字段的校验,所以email和phone的校验会再跑一次
  • 你定义的yup.test异步校验没有配置缓存逻辑,每次触发校验都会重新调用AuthService.checkEmail/checkPhone接口,没有复用之前的校验结果

解决方案

1. 配置YupResolver仅校验指定字段

如果你使用的是@hookform/resolvers里的yupResolver,初始化时开启partial模式,即可让trigger仅校验你指定的字段,不会执行全量schema校验:

import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';

const schema = yup.object({
  // 你的校验规则
});

useForm({
  resolver: yupResolver(schema, { partial: true }), // 开启partial模式
  // 其他表单配置
})

配置后第二步调用trigger时,就不会再触发第一步已经校验过的email字段的校验。

2. 提交时跳过重复全量校验(可选)

如果你能保证前面步骤的校验结果都是有效的,可以不用handleSubmit的默认校验逻辑,直接拿到表单值提交即可:

const handleRegister = () => {
  const formValues = getValues();
  // 直接提交formValues即可
}

3. 给异步校验增加缓存逻辑

针对同一个email/phone值避免重复发起请求,可以增加缓存存储校验结果:

// 定义缓存容器
const emailCheckCache = new Map();
const phoneCheckCache = new Map();

// 改造校验规则
email: email.test(
  'isUnique',
  translate('signupFormScheme.email_is_busy'),
  async (value) => {
    if (!value) return true;
    if (emailCheckCache.has(value)) return emailCheckCache.get(value);
    const checkResult = await AuthService.checkEmail(value) === true;
    emailCheckCache.set(value, checkResult);
    return checkResult;
  },
),
// phone字段校验规则同理增加缓存逻辑

内容的提问来源于stack exchange,提问作者Александр Бычков

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:57:00