【问题标题】:Event Emitter memory leak because of ReactJS Rerendering由于 ReactJS 重新渲染导致的 Event Emitter 内存泄漏
【发布时间】:2021-06-22 11:05:02
【问题描述】:

希望您今天过得愉快✌感谢您提前提供帮助。

我正在使用 ElectronJS 和 React 构建一个 Web 浏览器。我正在使用 ipcMain 和 ipcRenderer 在后端和前端之间发送事件,它们只是 EventEmitter 类的子类。

我正在处理的问题是 EventEmitter 泄漏。我的 React 前端发送一个事件,后端返回数据。 React 然后将此数据分配给它的状态,这会导致重新渲染,然后创建另一个事件侦听器。这会创建一堆事件侦听器,然后出现内存泄漏错误。

这是我的 React 组件的示例

export const CoreLayout = props => {

  const [tablist, setTablist] = useState([]);
  window.ipcRenderer.on('receive-tabs', (_, data) => {
    setTablist(data);
  });

  console.log('rerender2')

  return (
    <div className="flex flex-col w-full min-h-screen bg-night-600">
      <Header tablist={tablist} isMaximized={props.isMaximized} />
    </div>
  )

}

【问题讨论】:

  • 你应该使用useEffect来管理这样的订阅

标签: node.js reactjs electron eventemitter


【解决方案1】:

要在render 中实现副作用,您应该始终考虑useEffect。在您的情况下,当组件结束其生命周期(已卸载)时,您通常需要删除事件侦听器。

请参阅https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup,了解如何设置具有自动清理功能的副作用。为避免在每次渲染时重新运行它,您需要一个空的依赖数组,如黄色大注释部分所述:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉 React 你的效果不依赖于任何来自 props 或 state 的值,所以它永远不需要重新运行。

【讨论】:

  • 刚刚查看了一下,我需要它在重新渲染而不是卸载时删除所有事件侦听器。我可以通过在函数开头添加删除事件侦听器的函数来做到这一点,这样它会在每次渲染时删除旧的事件侦听器并创建新的事件侦听器。
【解决方案2】:
  useEffect(()=>{
    const listener= (_, data) => {
      setTablist(data);
    };
    window.ipcRenderer.on('receive-tabs', listener);
    
    return ()=>{
      window.ipcRenderer.removeListener('receive-tabs', listener);
    }
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    相关资源
    最近更新 更多