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原生编写能力。哎好好补基础了。

参考文章:
一起围观由React Hooks防抖引发的面试翻车现场

Last modification:November 2, 2021
如果觉得我的文章对你有用,请随意赞赏