javascript 在React useEffect钩子中清理Lodash去抖动函数

1qczuiv0  于 2023-06-04  发布在  Java
关注(0)|答案(3)|浏览(174)

我尝试使用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;
}
svgewumm

svgewumm1#

不需要传递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]);
fjaof16o

fjaof16o2#

将去抖动功能保留在useEffect之外,只需在useEffect中清理即可。

const debounceFunc = debounce((value) => {
    console.log('event', value);
  }, 1000);

  useEffect(() => {
    return () => {
      debounceFunc.cancel();
    };
  }, [debounceFunc]);

  function handleChange(
    event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ): void {
    debounceFunc(event.target.value);
  }
lymnna71

lymnna713#

而是直接调用cancel函数。你应该只使用debounced,这就是你在监听器中添加的内容:

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

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

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

相关问题