无法使用 EventListener 对已卸载的组件执行 React 状态更新

Dan*_*hid 3 javascript reactjs react-native react-hooks use-effect

我有以下代码片段,我收到两个警告:

警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。

unmountComponentAtNode():您尝试卸载的节点是由 React 的另一个副本渲染的。

    import React, { useState, useEffect } from "react";
    import GravatarList from "./GravatarList";
    import Header from "./Header";
    import { calculateNumberOfImages } from "./utils";
    
    const App = () => {
      const handle = () => {
        setState({ images: calculateNumberOfImages() });
      }
    
    
      useEffect(() => {
          return () => {
    
            window.removeEventListener('resize', () => handle())
            window.removeEventListener('scroll', () => handle())
          }
       }, [])
    
    
      const [state, setState] = useState(() => {
        
        window.addEventListener("scroll", () => handle());
        window.addEventListener("resize", () => handle());
      
        return { images: calculateNumberOfImages() };
      });
    
      return (
        <div>
          
          <Header />
          <GravatarList state={state} />
        </div>
      );
    };
    
    export default App;
Run Code Online (Sandbox Code Playgroud)

我似乎无法弄清楚我做错了什么,因为我已经清除了 中的听众useEffect

Dre*_*ese 5

这里的问题是您尝试删除的事件回调您开始添加的回调不同。问题是因为您使用匿名函数来调用更新状态的函数。

您也不应该使用状态初始值设定项函数来执行添加事件侦听器等副作用。

handle回调和添加事件侦听器移动到安装useEffect挂钩中。将handle回调引用传递给添加/删除函数,

const App = () => {
  const [state, setState] = useState(() => ({
    images: calculateNumberOfImages()
  }));

  useEffect(() => {
    const handle = () => {
      setState({ images: calculateNumberOfImages() });
    };

    window.addEventListener("scroll", handle);
    window.addEventListener("resize", handle);
  
    return () => {
      window.removeEventListener('resize', handle);
      window.removeEventListener('scroll', handle);
    }
   }, []);

  return (
    <div>
      <Header />
      <GravatarList state={state} />
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)