使用Electron时从未调用过useEffect清理

时间:2020-04-13 01:28:20

标签: reactjs electron

我正在使用带有React JS的Electron来构建我的应用程序,并使用myScheduledFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./bin Handler: myScheduledFunction Policies: - AWSLambdaBasicExecutionRole myRule: Type: AWS::Events::Rule Properties: Description: "ScheduledRule" ScheduleExpression: "rate(1 minutes)" State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "myScheduledFunction" - "Arn" PermissionForEventsToInvokeLambda: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "myScheduledFunction" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "myRule" - "Arn" myFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./bin Handler: myFunction Environment: Variables: RULE_NAME: !Ref myRule Policies: - AWSLambdaBasicExecutionRole - EventBridgePutEventsPolicy: EventBusName: default Events: SomeEvent: ... 来监听useEffect的事件。问题是,由于某种原因,useEffect订阅被调用两次,并且每次我使用cmd + R重新加载电子窗口时,其订阅都将再次被调用,并且ipcRenderer清理操作从未被调用,因此它开始堆叠ipcRender订阅。我的代码如下:

App.tsx

useEffect

index.tsx

import React, { useState, useEffect } from 'react';
import { NetworkRequest, networkRequest } from './models/request';
const { ipcRenderer } = window.require('electron');

const Home = () => {
  const homeState = useHomeState()
  return (
    <>
      <h1>Requests</h1>
      {/* Here i'll have a list with homeState.requests */}
    </>
  )
}

class InitialHomeState {
  requests: NetworkRequest[]

  constructor(requests: NetworkRequest[]) {
    this.requests = requests
  }
}

const useHomeState = () => {
  const [homeState, setHomeState] = useState(new InitialHomeState([]))
  useEffect(() => {
    function proxyRequestHandler(requestPayload: any) {
      setHomeState(state => {
        const newRequest = new NetworkRequest(requestPayload.hostname, requestPayload.url, networkRequest(requestPayload.method))
        const requests = state.requests
        requests.push(newRequest)
        return { ...state, requests }
      })
    } 
    console.log("SUBSCRIBING")
    ipcRenderer.on('proxy-new-request', (evt: any, payload: any) => {
      console.log(evt)
      proxyRequestHandler(payload)
    })

    return function unsubscribeProxyListener() {
      console.log("UNSUBSCRIBING")
      ipcRenderer.removeListener('proxy-new-request', proxyRequestHandler)
    }
  }, [])

  return homeState
}

const App = () => <Home/>

export default App

和电子main.ts

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

1 个答案:

答案 0 :(得分:2)

首先,感谢@hackape,它为以下解决方案打开了大门。

对于那些面临相同问题的人,我决心做以下事情:

  1. 在主电子文件上使用bool var以避免双重代理侦听器设置
if (!didSetupListener) {
            didSetupListener = true
            proxyServer.on('new-request', (request: NetworkRequest) => {
                mainWindow.webContents.send('proxy-new-request', request)
            })
        }
  1. 在React useEffect()上,检查它是否尚未订阅
if (ipcRenderer.rawListeners('proxy-new-request').length === 0) {
      ipcRenderer.on('proxy-new-request', (evt: any, request: NetworkRequest) => {
        proxyRequestHandler(request)
      })
    }

OBS:这可能不是正确的方法,但至少可以帮助我在开发过程中继续使用CMD + R。