如何在react / webpack 2设置中导入电子ipcRenderer

时间:2017-05-16 18:09:15

标签: reactjs webpack electron

使用电子,反应(es6 / jsx),sass,pouchdb和webpack 2设置。我无法导入或要求ipcRenderer在主进程和渲染器进程之间进行通信。我可以在此处找到我的设置:https://github.com/wende60/timeTracker

有关如何将ipcRenderer放入反应组件的任何提示吗?

干杯,乔

7 个答案:

答案 0 :(得分:3)

我遇到了同样的问题。这为我解决了这个问题:

添加webpack.config.js

const webpack = require("webpack");

module.exports = {
    plugins: [
        new webpack.ExternalsPlugin('commonjs', [
            'electron'
        ])
    ]
    ...
}

然后您可以将其与

一起使用
import {ipcRenderer} from "electron";

答案 1 :(得分:2)

const electron = window.require('electron');
const ipcRenderer  = electron.ipcRenderer;

我认为这是更好的解决方案,因为它避免弹出React应用。

答案 2 :(得分:1)

建议您阅读我的回复here

您将要这样设置应用程序:

main.js

const {
  app,
  BrowserWindow,
  ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

async function createWindow() {

  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      enableRemoteModule: false, // turn off remote
      preload: path.join(__dirname, "preload.js") // use a preload script
    }
  });

  // Load app
  win.loadFile(path.join(__dirname, "dist/index.html"));

  // rest of code..
}

app.on("ready", createWindow);

ipcMain.on("toMain", (event, args) => {
  fs.readFile("path/to/file", (error, data) => {
    // Do something with file contents

    // Send result back to renderer process
    win.webContents.send("fromMain", responseObj);
  });
});

preload.js

**更新:请勿使用send键值作为属性名称。当您尝试在主进程win.webContents.send中调用win.webContents.send('your_channel_name')时,它将覆盖main.js方法,并且什么也不做。最好使用更好的名称,例如requestresponse

const {
    contextBridge,
    ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        //send: (channel, data) => {
        request: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        //receive: (channel, func) => {
        response: (channel, func) => {
            let validChannels = ["fromMain"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);

index.html

<!doctype html>
<html lang="en-US">
<head>
    <meta charset="utf-8"/>
    <title>Title</title>
</head>
<body>
    <script>
        window.api.response("fromMain", (data) => {
            console.log(`Received ${data} from main process`);
        });
        window.api.request("toMain", "some data");
    </script>
</body>
</html>

答案 3 :(得分:0)

使用webpack-target-electron-renderer为此问题找到了一个很好的解决方案因此,我可以使用热重新加载在localhost环境中开发Web部件。电子仅在电子环境中需要。

你可以在这里看到一个有效的例子: https://github.com/wende60/webpack-web-and-electron-example,来自acao的webpack-web-and-electron-example,并针对webpack 2和hot-replacement进行了更新。

如果您对网络包,电子,反应,sass和pouchdb安装感兴趣,请查看: https://github.com/wende60/timeTracker 工作仍在进行中......

答案 4 :(得分:0)

我最近一直在研究这个话题,我找到了在电子main.js和应用程序的React部分之间做一些ipc的解决方案。由于import {ipcRenderer} from 'electron';将插件添加到webpack模块并const ipc = require('electron').ipcRenderer;产生了一些错误后,我最终在结果页面中需要电子并将其添加到窗口中。

index.html我做了类似的事情

<body>
  ...
  <script>
    window.ipc = require('electron').ipcRenderer;
  </script>
  <div id="root">
  </div>
  ...
</body>

在做出反应index.js时,我做了类似的事情:

import React from 'react';
import ReactDOM from 'react-dom';
// ...
if(window.ipc)
ipc.on("some-event", (event, someParameter) => {
  ReactDOM.render(
    <SomeElement value={someParameter} />,
    document.getElementById("root")
  );
})
// ...

为了完成这项工作,我从电子应用程序启动了反应页面,在main.js我做了类似的事情。

const {app, BrowserWindow} = require("electron"};
const exec = require("child_process").exec;

let main;
app.on("ready", () => {
  exec("node start", (err, stdout, stderr) => {
    if(err) console.log(err);
    console.log("" + stdout);
    console.log("" + stderr);
  });

  main = new BrowserWindow();
  main.loadURL("http://localhost:3006");
  main.on("close", () => {main = null});
});

因为电子在同一个端口上运行,我在我的项目中添加了一个.env文件,其中包含

PORT=3006

我使用create-react-app my-prjnpm install -g create-react-app)命令为我的基础项目看起来像这样

my-prj
 |-package.json
 |-main.js
 |-.env
 |-node_modules/
 |-public/
    |-index.html
 |-src/
    |-index.js

希望这篇文章有任何帮助。

答案 5 :(得分:0)

截至2020年5月,我认为Erik Martín Jordán has said it best

创建一个preload.js文件:

total()

在main.js上:

window.ipcRenderer = require('electron').ipcRenderer;
该文件上的

mainWindow变量将预加载preload.js文件。现在,React组件可以调用window.ipcRenderer方法。

在React app.js中:


// Create the browser window.
mainWindow = new BrowserWindow({
    alwaysOnTop: true,
    frame: false,
    fullscreenable: false,
    transparent: true,
    titleBarStyle: 'customButtonsOnHover',
    show: false,
    width: 300, 
    height: 350,
    webPreferences: {
        nodeIntegration: true,
        preload: __dirname + '/preload.js'
    }
});

// Blur window when close o loses focus
mainWindow.webContents.on('did-finish-load', () => mainWindow.webContents.send('ping', '?') );

答案 6 :(得分:-1)

import { ipcRenderer } from "electron"
import { Component } from "react"

...

class MyComponent extends Component {
   render(){
      ipcRenderer.send("event", "some data")
      return (<div>Some JSX</div>)
   }
}