首页  >  问答  >  正文

使用React中的防抖hooks的方法

import { useEffect, useState } from 'react';

export default function useDebounce(text: string, delay: number) {
  const [value, setValue] = useState('');

  useEffect(() => {
    const timerId = setTimeout(() => {
      setValue(text);
    }, delay);
    return () => {
      clearTimeout(timerId);
    };
  }, [text, delay]);
  return value;
}


我曾经制作和使用 useDebounce 钩子。 但是,在调整大小事件中使用 useDebounce 存在一些问题。 useDebounce hook 必须在组件顶部运行,因为它在内部使用了 useEffect。 但是,调整大小函数设置为在 useEffect 上运行,如下所示。

此外,上面的代码将值作为一个因素,但我认为我们需要接收它作为回调才能使用下面的代码。

  useEffect(() => {
    const handler = () => {
      if (liRef.current) setWidth(liRef.current.clientWidth);
    };

    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);

如何使用上面的代码来利用现有的useDebounce?

P粉497463473P粉497463473287 天前410

全部回复(2)我来回复

  • P粉098417223

    P粉0984172232024-01-29 11:40:03

    如果你直接在React组件中使用debounced函数,它将不起作用,因为每个渲染都会创建一个新函数,相反,你可以使用这个useDebounce钩子:

    function useDebounce(callback, delay) {
      const callbackRef = React.useRef(callback)
      React.useLayoutEffect(() => {
        callbackRef.current = callback
      })
      return React.useMemo(
        () => debounce((...args) => callbackRef.current(...args), delay),
        [delay],
      )
    }
    

    useRef 确保它与上次提供的函数相同,并且 useLayoutEffect 确保在每次渲染时,对函数的引用都会更新。

    有关这方面的更多信息,请参阅“最新参考”模式反应

    回复
    0
  • P粉894008490

    P粉8940084902024-01-29 09:59:42

    我认为与其通过useEffect实现去抖,不如将去抖逻辑实现为一个函数。

    useEffectdeps 引用的状态改变时执行。也就是说,由于是一个如果只按照执行流程就容易漏掉的逻辑,所以后期维护时很难弄清楚这个useEffect是从哪一个流程衍生出来的,调试起来也比较困难。

    示例

    自定义反跳

    function debounce(func, timeout = 300) {
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(this, args);
        }, timeout);
      };
    }
    
    function saveInput() {
      console.log('Saving data');
    }
    const processChange = debounce(() => saveInput());
    
    
    

    如果您使用lodash,则只需导入即可使用它。

    Lodash Debounce

    import { debounce } from 'lodash';
    
    const debounceOnChange = debounce(() => {
      console.log("This is a debounce function");
    }, 500);
    

    希望这有帮助:)

    回复
    0
  • 取消回复