简体   繁体   English

在 React useEffect hook 中清理 Lodash debounce function

[英]Cleaning up Lodash debounce function in React useEffect hook

I'm trying to use Lodash's Debounce function with a custom hook to prevent the window resize event from firing too often.我正在尝试使用 Lodash 的 Debounce function 和自定义挂钩来防止 window 调整大小事件过于频繁地触发。 Whilst the hook works as desired, I am struggling to properly cleanup in the function returned from the React useEffect hook.虽然钩子按需要工作,但我正在努力正确清理从 React useEffect 钩子返回的 function。 This results in the following error in the browser console as well as the event listener existing for the entirety of the users session in the single-page app.这会导致浏览器控制台中出现以下错误,并且单页应用程序中的所有用户 session 都存在事件侦听器。

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.

I understand there are ways of rolling a custom debounce hook, but for the sake of this project that uses Lodash heavily I would prefer to stick with the Debounce function if possible.我知道有一些方法可以滚动自定义 debounce hook,但是为了这个大量使用 Lodash 的项目,如果可能的话,我宁愿坚持使用 Debounce function。

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;
}

There is not need to pass debounce.cancel() .不需要通过debounce.cancel() While removing the event listener you need to pass the same reference to the function that is used while creating the listener.删除事件侦听器时,您需要将相同的引用传递给创建侦听器时使用的 function。 You can also cancel the current debounced function.您也可以取消当前的去抖 function。

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]);

You're directly calling cancel function rather.您是直接调用 cancel function 而不是。 You should just use debounced that's what added in your listener:您应该只使用debounced这就是在您的侦听器中添加的内容:

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

In most cases, just removing the event is fine:在大多数情况下,只需删除事件就可以了:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM