搜索栏和过滤器同时触发时如何避免重复请求?
我现在在做一个电商产品页面,用户可以通过搜索框输入关键词,同时用下拉框选择分类进行过滤。但发现当用户同时修改搜索词和分类时,会连续发送多次请求。比如先改分类再改搜索词,间隔0.5秒内就会触发两次请求,导致加载卡顿。
之前给两个输入框都加了防抖,代码大概是这样的:
const searchDebounce = useDebounce(searchInput, 500);
const filterDebounce = useDebounce(filterValue, 500);
useEffect(() => {
fetchData({ query: searchDebounce, category: filterDebounce });
}, [searchDebounce, filterDebounce]);
但这样还是不行,因为两个防抖是独立的。现在想改成只要任意一个字段变化就重置计时器,但不确定怎么合并这两个状态的变化。有没有更好的方式让两个输入联动时只触发一次请求?
第一步:合并状态变化
我们可以把搜索词和分类的状态组合成一个对象,然后对这个对象进行防抖处理。这样,只要任意一个字段发生变化,都会触发同一个防抖逻辑。
这里我们用了一个对象
combinedState来存储搜索词和分类的状态,然后对这个对象进行防抖。这样可以确保无论哪个字段发生变化,都会触发同一个防抖逻辑。第二步:监听防抖后的状态
接下来,我们在组件中使用这个合并的防抖状态,并在它的变化时触发请求。
在这个实现中,
debouncedState是一个防抖后的对象,包含query和category两个字段。当用户修改搜索框或下拉框时,debouncedState会在 500 毫秒后更新,触发useEffect中的请求逻辑。第三步:为什么这样做有效
1. 统一防抖逻辑:通过将搜索词和分类的状态合并为一个对象,我们避免了两个独立防抖状态分别触发请求的问题。
2. 重置计时器:无论用户修改哪个输入框,都会更新
combinedState,从而重置防抖计时器。只有在用户停止操作一段时间后,才会真正触发请求。3. 减少不必要的请求:这种方式可以显著减少短时间内多次请求的情况,提升页面性能。
注意事项
- 如果你的项目中没有现成的
useDebounce钩子,可以用lodash.debounce或者手写一个简单的防抖函数。- 如果需要支持更复杂的过滤条件(比如多选、价格区间等),也可以扩展
combinedState的结构,原理是一样的。这种做法在实际开发中很常见,尤其是涉及到多个联动输入的场景。希望这个方案能解决你的问题!