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

React Hook Form中解构isValid触发异常验证的原理探究

React Hook Form中解构useFormState的isValid引发验证行为变化的原因

我在React Hook Form库中发现一个有趣的现象:

  • 当解构useFormState返回的isValid属性时(即便完全不调用或使用它),输入框每一次按键都会触发字段的validate方法;
  • 但如果不解构isValid,只解构errors这类属性,验证仅在输入框失焦(blur)时触发,符合配置的mode: "onBlur"预期。

背后的原理:Proxy对象

这个“魔法”行为的核心是Proxy对象。React Hook Form的useFormState返回的是一个被Proxy包装的状态对象:

  • 当你解构isValid时,会触发Proxy的get拦截陷阱。isValid代表整个表单的验证状态,要计算它的值,必须实时校验所有字段的合法性,因此会主动调用字段的validate方法;
  • 每次输入按键会触发组件重新渲染,此时解构isValid的操作会重复触发上述的Proxy拦截与全局验证逻辑,导致validate方法被重复调用;
  • 而仅解构errors时,errors是针对单个字段的错误信息,不需要触发全局的实时验证计算,因此验证行为保持配置的onBlur时机,仅在失焦时触发。

示例代码

import React from "react";
import ReactDOM from "react-dom";
import {
  Controller,
  FormProvider,
  useForm,
  useFormState
} from "react-hook-form";

import "./styles.css";

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const Input = () => {
  // 解开这行注释,输入框每次按键都会触发validate
  // const { isValid } = useFormState(); 

  const { errors } = useFormState();

  return (
    <>
      <label htmlFor="username">用户名</label>
      <Controller
        defaultValue=""
        name="username"
        rules={{
          validate: async (value) => {
            console.log("为什么解构isValid后会打印这条日志?");
            await sleep(1000);
            return value === "bill";
          }
        }}
        render={({ field }) => (
          <input
            onChange={field.onChange}
            onBlur={field.onBlur}
            value={field.value}
            name="username"
            placeholder="请输入bill"
          />
        )}
      />
      <input type="submit" />
    </>
  );
};

function App() {
  const methods = useForm({
    mode: "onBlur",
    reValidateMode: "onChange"
  });

  return (
    <FormProvider {...methods}>
      <form onSubmit={console.log}>
        <Input />
      </form>
    </FormProvider>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:30:14