如何在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
相关产品推荐
相关产品推荐

