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

为何React Hook Form中formState.errors会引发组件多次重渲染?

React Hook Form表单提交后组件多次重渲染问题

问题详情

使用React、TypeScript和React Hook Form(v7.52.1)开发表单时,发现提交表单后,无论formState.errors是否存在错误,组件都会触发多次重渲染。查阅官方文档未找到相关说明,不确定这是预期行为、Bug还是实现问题。

环境说明

  • 未启用React Strict Mode
  • React Hook Form版本:7.52.1

示例代码

import * as React from "react";
import * as ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

type FormInputs = {
  firstName: string;
};

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormInputs>({
    defaultValues: {
      firstName: "",
    },
  });

  function onSubmit() {
    console.log("onSubmit");
  }

  console.log("errors", errors);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>First Name</label>
      <br />
      <input type="text" {...register("firstName", { required: true })} />
      <br />
      <input type="submit" />
    </form>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

预期行为

表单提交后组件仅重渲染一次。


原因分析

这属于React Hook Form的预期行为,表单提交流程中会经历多个状态更新环节:

  1. 提交触发时,isSubmitting状态从false切换为true;
  2. 执行验证逻辑,更新errors状态;
  3. 验证完成后,isSubmitting切回false,同时isSubmitted状态更新为true。

这些状态都属于formState的一部分,每次formState内部状态变化时,都会生成新的formState引用。由于你在组件中解构了formState.errors,React会感知到引用变化并触发重渲染——即使errors的内容没有变化,引用更新也会导致重渲染。


解决方案

1. 精准监听特定字段错误

使用useWatch只监听你关心的字段错误,避免因整个formState变化触发不必要的重渲染:

import { useForm, useWatch } from "react-hook-form";

// 在组件内部
const { register, handleSubmit, control } = useForm<FormInputs>({
  defaultValues: { firstName: "" },
});
// 仅监听firstName字段的错误
const firstNameError = useWatch({
  control,
  name: "firstName.error",
});

2. 缓存错误对象(减少引用变化触发的重渲染)

通过useMemo缓存errors,仅当错误内容实际变化时才更新:

const { formState } = useForm<FormInputs>({ /* 配置项 */ });
const errors = useMemo(() => formState.errors, [JSON.stringify(formState.errors)]);

注意:这种方式依赖JSON序列化,只适合简单的错误结构。

3. 使用React.memo优化组件

如果组件本身逻辑复杂,可以用React.memo包裹组件,通过浅比较props减少重渲染(需确保组件依赖的props变化是必要的):

const App = React.memo(() => {
  // 组件逻辑...
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:51:17