【问题标题】:Cleaning up Lodash debounce function in React useEffect hook在 React useEffect 挂钩中清理 Lodash 去抖动功能
【发布时间】:2020-05-13 16:08:18
【问题描述】:

我正在尝试将 Lodash 的 Debounce 函数与自定义挂钩一起使用,以防止窗口调整大小事件过于频繁地触发。虽然钩子按需要工作,但我正在努力正确清理从 React useEffect 钩子返回的函数。这会导致浏览器控制台中出现以下错误,并且单页应用程序中的整个用户会话都存在事件侦听器。

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

我知道有一些方法可以滚动自定义 debounce 挂钩,但是为了这个大量使用 Lodash 的项目,如果可能的话,我更愿意坚持使用 Debounce 功能。

function getSize() {
  return {
    width: window.innerWidth,
    height: window.innerHeight,
  };
}

export default function useWindowSize(debounceDelay = 500) {
  const [windowSize, setWindowSize] = useState(getSize);

  useEffect(() => {
    function handleResize() {
      setWindowSize(getSize());
    }

    const debounced = debounce(handleResize, debounceDelay);
    window.addEventListener(`resize`, debounced);

    return () => window.removeEventListener(`resize`, debounced.cancel());
  }, [debounceDelay]);

  return windowSize;
}

【问题讨论】:

    标签: javascript reactjs lodash


    【解决方案1】:

    不需要传递debounce.cancel()。删除事件侦听器时,您需要将相同的引用传递给创建侦听器时使用的函数。您也可以取消当前的去抖功能。

    useEffect(() => {
        function handleResize() {
          setWindowSize(getSize());
        }
    
        const debounced = debounce(handleResize, debounceDelay);
        window.addEventListener(`resize`, debounced);
    
        return () => {
             debounce.cancel()
             window.removeEventListener(`resize`, debounced); // use debounced directly
         }
      }, [debounceDelay]);
    

    【讨论】:

    • 无论是 cancel() 都不需要清理。
    • 如果你不取消调用,一个已经在进行的去抖动函数调用将导致警告。
    • 谢谢。展示如何使用cancel() 来防止去抖函数触发也很有帮助。
    【解决方案2】:

    您是直接调用取消函数。您应该只使用debounced,这就是在您的侦听器中添加的内容:

    return () => {
      window.removeEventListener('resize', debounced)
    }
    

    在大多数情况下,只需删除事件即可:

    return () => {
      window.removeEventListener('resize')
    }
    

    【讨论】:

    • 您的第一个选项有效,但第二个选项返回 TypeError,因为 removeEventListener 需要至少 2 个参数,类型和侦听器。
    • 我说的是大多数情况。在您的情况下,第一个选项将起作用
    猜你喜欢
    • 2023-01-25
    • 2020-03-05
    • 1970-01-01
    • 2017-05-03
    • 2021-02-07
    • 1970-01-01
    • 2016-07-17
    • 1970-01-01
    • 2021-12-24
    相关资源
    最近更新 更多