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

如何在react-hook-form中isDirty=true时避免重复提交相同表单值?

解决react-hook-form搜索表单仅在值真正变化时提交的问题

你用useState存上次值的思路是可行的,但用useRef替代会更高效——毕竟我们只是需要一个不触发重渲染的存储容器,没必要让组件因为存个比较值反复刷新。下面给你两个实用方案:

方案一:用useRef+深度比较控制提交

核心思路是用useRef存储上次成功提交的表单值,提交时和当前值做深度比较,只有确实变化时才执行搜索逻辑。

代码示例

import { useForm } from 'react-hook-form';
import { useRef } from 'react';
// 可以用lodash的isEqual,也可以自己实现深度比较函数
import { isEqual } from 'lodash';

function SearchForm() {
  const { register, handleSubmit, getValues } = useForm({
    defaultValues: {
      name: '',
      mail: ''
    }
  });
  // 存储上次提交的有效表单值
  const lastSubmittedValues = useRef(null);

  const onSubmit = (data) => {
    // 第一次提交直接执行
    if (!lastSubmittedValues.current) {
      // 这里替换成你的搜索逻辑
      console.log('执行搜索:', data);
      lastSubmittedValues.current = { ...data };
      return;
    }

    // 深度比较当前值与上次提交值
    const valuesChanged = !isEqual(data, lastSubmittedValues.current);
    if (valuesChanged) {
      console.log('执行搜索:', data);
      lastSubmittedValues.current = { ...data };
    } else {
      console.log('表单值未变化,跳过提交');
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name')} placeholder="姓名" />
      <input {...register('mail')} placeholder="邮箱" />
      <button type="submit">搜索</button>
    </form>
  );
}

自定义深度比较函数(不用lodash)

如果不想引入第三方库,自己写个简单的深度比较函数也能满足需求:

function isDeepEqual(obj1, obj2) {
  // 基本类型直接比较
  if (obj1 === obj2) return true;
  // 排除非对象/空值情况
  if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 == null || obj2 == null) {
    return obj1 === obj2;
  }
  // 比较键的数量
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  if (keys1.length !== keys2.length) return false;
  // 递归比较每个键的值
  for (const key of keys1) {
    if (!keys2.includes(key) || !isDeepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }
  return true;
}

注意:别用dirtyFields判断

react-hook-form的dirtyFields是和表单初始默认值比较的,不是和上次提交值比较。比如你第一次提交了{name: 'sample1', mail: 'sample@test.com'},之后把name改成sample又改回sample1,此时dirtyFields会标记name为脏,但实际值和上次提交的完全一样,所以这个属性不适合你的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:00:25