防抖函数在react hooks中的实现

一、起因

lodash在react hooks中没成功,每次react函数调用都会产生一个新的timer实例同时旧的timer实例还存在,并没有clear掉失去了debounce的意义

二、自己动手写

在搞清楚debounce函数的原理之后,自己结合网上的写法实现了一版如下

 /**
   * @desc: 防抖函数
   * @param {*} fn
   * @param {*} delay
   */
function useDebounce(fn: Function, delay: number) {
    const {current} = useRef({fn, timer: null as unknown as NodeJS.Timeout});
    useEffect(function() {
      current.fn = fn;
    }, [current.fn, fn]);

    return useCallback(function(...args: any[]) {
      if (current.timer) {
        clearTimeout(current.timer as unknown as number);
      }
      current.timer = setTimeout(() => {
        current.fn.call(current.fn, ...args);
      }, delay);
    }, [current.fn, current.timer, delay]);
  }

useRef返回相当于一个{current: ...}的plain object,但是和正常这样每轮render之后直接显式创建的区别在于,每轮render之后的useRef返回的plain object都是同一个,只是里面的current发生变化

而且,当里面的current发生变化的时候并不会引起render

通过useRef创建了一个对象引用,初始值为fn和timer,它会在这个函数组件的生命周期内一直存在,拿这个做引用标识是否存在计时器,

useEffect是react hooks的副作用函数,执行在渲染之后,详细介绍可以看官网https://zh-hans.reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

每次return后current都会更新,current一更新,就触发useEffect重新赋值fn

useCallback是根据依赖项是否变化返回一个新函数,如下图,current更新后,每次先判断timer是否存在,这是timer是缓存中的timer会被清除掉,赋予新current一个新timer

这样,如果触发fn函数停止的话就会触发最新的settimeout

const debounce = useDebounce(fn, 1000); //延迟1秒执行

debounce在input onchange事件中作为回调函数出现,这样就实现了hooks函数防抖。

如果错误,欢迎指正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值