最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using Electron's ipcRender from inside a React component - Stack Overflow

programmeradmin8浏览0评论

I am trying to create a small React app that captures and sets a global shortcut, that will be used to show and hide the Electron app window. However I have bee stuck, as when I try to use ipcRender, from inside a React ponent, the following error is thrown.

Uncaught Error: Cannot find module "fs"

I am using Webpack to bundle my JS and pile JSX, and ES6 syntax to import Electron and ipcRender, as you can see in my ponent code below.

import React from "react";
import electron, { ipcRenderer } from 'electron';

var event2string = require('key-event-to-string')({});

export default React.createClass({
    getInitialState: function() {
        return {shortcut: this.props.globalShortcut[0]};
    },
    handleOnKeyDown:function(e){
        e.preventDefault();
        var keys = event2string(e);
        this.setState({shortcut:keys});

        this.props.globalShortcut.splice(0, 1);
        this.props.globalShortcut.push(keys);
    },
    handleOnKeyUp:function(){
        this.refs.shortcutInput.value = this.state.shortcut;
        this.refs.shortcutInput.blur();
        ipcRenderer.send('set-new-shortcut', this.props.globalShortcut);
    },
    handleOnFocus:function(){
        this.refs.shortcutInput.value = '';
    },
    render() {
        return (
            <div id="settings-container">
                <h1>The show/hide shortcut is "{this.state.shortcut}"</h1>
                <form role="form">
                    <input type="text" ref="shortcutInput" placeholder="Create new shortcut" onFocus={this.handleOnFocus} onKeyDown={this.handleOnKeyDown} onKeyUp={this.handleOnKeyUp} className="form-control form-field"/>
                </form>
            </div>
        );
    }
});

I've tried different solutions, such as adding a node-loader & json-loader to my Webpack file , adding the node object with fs set to 'empty', including a plugin that tells Webpack to ignore fs and ipc and install fs via npm. I can't get any of them to work.

Unfortunately I don't have enough knowledge of Webpack or ES6 syntax to figure out what's going on, and most of the solutions I've tried have been in a 'paste-and-hope' fashion. So if anyone could explain, in laymen's terms what's happening, I'll be able to dig some more.

Below is my current Webpack file.

var webpack = require('webpack');

module.exports = {
  context: __dirname + '/src/js',
  entry: "./index.js",

  output: {
    filename: 'bundle.js',
    path: __dirname + '/build',
    publicPath: 'http://localhost:8080/build/'
  },

  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, query:{presets:['es2015','react']} },
      { test: /\.scss$/, loader: 'style-loader!css-loader!sass-loader' }
    ]
  },

  // Don't know if below is working, 'Uncaught Error: Cannot find module "fs"' error still thrown when trying to import electron
  plugins: [ 
    new webpack.IgnorePlugin(new RegExp("^(fs|ipc)$"))
  ],

  // Don't know if below is working, 'Uncaught Error: Cannot find module "fs"' error still thrown when trying to import electron
  node: {
    fs: 'empty'
  }
};

I am trying to create a small React app that captures and sets a global shortcut, that will be used to show and hide the Electron app window. However I have bee stuck, as when I try to use ipcRender, from inside a React ponent, the following error is thrown.

Uncaught Error: Cannot find module "fs"

I am using Webpack to bundle my JS and pile JSX, and ES6 syntax to import Electron and ipcRender, as you can see in my ponent code below.

import React from "react";
import electron, { ipcRenderer } from 'electron';

var event2string = require('key-event-to-string')({});

export default React.createClass({
    getInitialState: function() {
        return {shortcut: this.props.globalShortcut[0]};
    },
    handleOnKeyDown:function(e){
        e.preventDefault();
        var keys = event2string(e);
        this.setState({shortcut:keys});

        this.props.globalShortcut.splice(0, 1);
        this.props.globalShortcut.push(keys);
    },
    handleOnKeyUp:function(){
        this.refs.shortcutInput.value = this.state.shortcut;
        this.refs.shortcutInput.blur();
        ipcRenderer.send('set-new-shortcut', this.props.globalShortcut);
    },
    handleOnFocus:function(){
        this.refs.shortcutInput.value = '';
    },
    render() {
        return (
            <div id="settings-container">
                <h1>The show/hide shortcut is "{this.state.shortcut}"</h1>
                <form role="form">
                    <input type="text" ref="shortcutInput" placeholder="Create new shortcut" onFocus={this.handleOnFocus} onKeyDown={this.handleOnKeyDown} onKeyUp={this.handleOnKeyUp} className="form-control form-field"/>
                </form>
            </div>
        );
    }
});

I've tried different solutions, such as adding a node-loader & json-loader to my Webpack file , adding the node object with fs set to 'empty', including a plugin that tells Webpack to ignore fs and ipc and install fs via npm. I can't get any of them to work.

Unfortunately I don't have enough knowledge of Webpack or ES6 syntax to figure out what's going on, and most of the solutions I've tried have been in a 'paste-and-hope' fashion. So if anyone could explain, in laymen's terms what's happening, I'll be able to dig some more.

Below is my current Webpack file.

var webpack = require('webpack');

module.exports = {
  context: __dirname + '/src/js',
  entry: "./index.js",

  output: {
    filename: 'bundle.js',
    path: __dirname + '/build',
    publicPath: 'http://localhost:8080/build/'
  },

  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, query:{presets:['es2015','react']} },
      { test: /\.scss$/, loader: 'style-loader!css-loader!sass-loader' }
    ]
  },

  // Don't know if below is working, 'Uncaught Error: Cannot find module "fs"' error still thrown when trying to import electron
  plugins: [ 
    new webpack.IgnorePlugin(new RegExp("^(fs|ipc)$"))
  ],

  // Don't know if below is working, 'Uncaught Error: Cannot find module "fs"' error still thrown when trying to import electron
  node: {
    fs: 'empty'
  }
};
Share Improve this question asked Sep 5, 2016 at 14:16 adotellisonadotellison 731 silver badge6 bronze badges 3
  • fs is a module. Try importing/requiring – Andrew Li Commented Sep 5, 2016 at 14:19
  • I just tried adding import fs from 'fs'; before import electron, { ipcRenderer } from 'electron'; and the error is still thrown. I also tried it with fs installed via npm --save-dev. – adotellison Commented Sep 5, 2016 at 14:35
  • This is where the error is taking place in my bundle.js var _fs = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"fs\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); – adotellison Commented Sep 5, 2016 at 14:37
Add a ment  | 

2 Answers 2

Reset to default 4

You need to set target: 'electron-renderer' in your Webpack config, if you still have issues after that take a look at https://github./chentsulin/electron-react-boilerplate

By using contextBridge we can resolve this issue

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

new BrowserWindow({
    width: 1200,
    height: 800,
    backgroundColor: "white",
    webPreferences: {
      nodeIntegration: false,
      worldSafeExecuteJavaScript: true,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  })

//example to display notification
ipcMain.on('notify', (_, message) => {
   new Notification({title: 'Notification', body: message}).show();
})

preload.js

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

contextBridge.exposeInMainWorld('electron', {
  notificationApi: {
    sendNotification(message) {
      ipcRenderer.send('notify', message);
    }
  }
})

then using the below code in your reactjs ponent will trigger a native notification message

import * as React from "react";
import * as ReactDOM from "react-dom";

class App extends React.Component {
  ponentDidMount() {
    electron.notificationApi.sendNotification("My custom message!");
  }
  render() {
    return <h1>contextBridge</h1>;
  }
}
发布评论

评论列表(0)

  1. 暂无评论