Очистка useEffect никогда не вызывается при использовании Electron - PullRequest
0 голосов
/ 13 апреля 2020

Я использую Electron с React JS для создания своего приложения и использую useEffect для прослушивания событий ipcRenderer. Проблема в том, что по какой-то причине подписка useEffect вызывается дважды, и каждый раз, когда я перезагружаю окно Electron с помощью cmd + R, оно снова подписывается, и очистка useEffect никогда не вызывается, поэтому он начинает составлять подписки ipcRender. Мой код следующий:

App.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

index.tsx

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

и Electron main.ts

const { app, BrowserWindow } = require('electron')
const hoxy = require('hoxy')
const fs = require('fs')

var proxy = hoxy.createServer({
    certAuthority: {
        key: fs.readFileSync(`${__dirname}/my-private-root-ca.key.pem`),
        cert: fs.readFileSync(`${__dirname}/my-private-root-ca.crt.pem`)
      }
}).listen(8080);

app.on('ready', () => {

    this.mainWindow = new BrowserWindow({width: 800, height: 600, webPreferences: { nodeIntegration: true }})
    this.mainWindow.loadURL('http://localhost:3000/')
    this.mainWindow.webContents.openDevTools();

    this.mainWindow.webContents.on('did-finish-load', () => {
        proxy.intercept('request', (req, res, cycle) => {
            this.mainWindow.webContents.send('proxy-new-request', { headers: req.headers, protocol: req.protocol, hostname: req.hostname, method: req.method, url: req.url });
        });
    });

});

1 Ответ

1 голос
/ 19 апреля 2020

Во-первых, спасибо @hackape, который открывает мне путь к следующему решению.

Для тех, кто сталкивается с той же проблемой, я решил сделать следующее:

  1. Использовать bool var в основном электронном файле, чтобы избежать настройки прослушивателя с двойным прокси
if (!didSetupListener) {
            didSetupListener = true
            proxyServer.on('new-request', (request: NetworkRequest) => {
                mainWindow.webContents.send('proxy-new-request', request)
            })
        }
В React useEffect(), проверьте, не подписано ли оно уже
if (ipcRenderer.rawListeners('proxy-new-request').length === 0) {
      ipcRenderer.on('proxy-new-request', (evt: any, request: NetworkRequest) => {
        proxyRequestHandler(request)
      })
    }

OBS: Возможно, это неправильный способ, но, по крайней мере, это помогло мне продолжать использовать CMD + R при разработке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...