由于 ReactJS 重新渲染,事件发射器内存泄漏

Event Emitter memory leak because of ReactJS Rerendering

祝您今天过得愉快✌感谢您的提前帮助。

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

的子级

我正在处理的问题是 EventEmitter 泄漏。我的 React 前端发送一个事件,后端 returns 数据。 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>
  )

}

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

https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup for instructions how to set up a side effect with an automatic clean-up. To avoid re-running this on each render, you'll want an empty dependency array, as described here in the big, yellow Note section: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

  useEffect(()=>{
    const listener= (_, data) => {
      setTablist(data);
    };
    window.ipcRenderer.on('receive-tabs', listener);
    
    return ()=>{
      window.ipcRenderer.removeListener('receive-tabs', listener);
    }
  });