React 中自定义防抖函数
最近在做一个React
的项目,中间做到搜索提示这个功能的时候遇到了请求次数过多的问题,当然对于这种情况肯定需要防抖来是请求延后发送,避免提示框随用户输入切换过于频繁,影响交互体验。
首先实现一个经典的防抖函数,这有什么难的嘛:
export const debounce = (fn, delay) => {
let time = null;
return function(...args) {
if(time) {
clearTimeout(time);
}
time = setTimeout(() => {
fn.apply(this, args);
}, delay)
}
}
然后在函数组件中使用:
useEffect(() => {
getSearchRes();
}, [dispatch, keywords]);
/* 其他逻辑 */
//防抖函数处理
const getSearchRes = debounce(() =>
//请求函数放置在redux中
dispatch(getSearchKeywordsResAction(keywords, { offset: 0, limit: 4 }))
);
最后保存测试,发现连续输入并不是在最后一次输入后延时发送请求,而是每次输入都会发送请求,只是每次发送请求延时了而已。这咋没用哇。
之后查阅了其他网站后发现了问题,还是自己对React hooks
不熟悉哇,当我们输入时改变keywords
,都会导致函数组件重新刷新执行,所以里面所有的hooks都会重新执行,我定义的普通函数也会重新执行。防抖函数中的time
每次都是定义一个新的,并没有保存到time
的状态,毕竟防抖的关键就是利用闭包保存time
变量。所以要保存time
这个变量使其在整个组件声明周期不变,于是就想到了useRef
这个hook
。
解决方式有了,我们可以考虑编写自定义hooks
来实现这个功能:
import { useRef } from 'react';
//防抖函数
export const useDebounce = (fn, delay = 200) => {
//todo 关于react hooks 中的防抖实现
const { current } = useRef({});
return function (...args) {
if (current.time) {
clearTimeout(current.time);
}
current.time = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
这样就使得防抖函数生效了。
通过这个案例其实也是让我知道了React真的能反映一个人JS原生编写能力。哎好好补基础了。