简体   繁体   中英

Electron Error with IPCRenderer in the render process

Im learning Electron and more nodes, but I keep getting an error everytime I interact with IPC Renderer.

render.js:6 Uncaught ReferenceError: Cannot access 'ipc' before initialization
at updateRP (render.js:6)
at HTMLButtonElement.onclick (index.html:11)

As far as I can tell from various forums, the issue should have been fixed when I added the nodeIntergation to my main process. Im really confused, any help with this would be much appreciated.

CODE: HTML

<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <h1>💖 Hello World!</h1>
    <p>Welcome to your Electron application.</p>
    <button onclick="updateRP()">Update RP</button>
    <script type="text/javascript" src="render.js"></script>
  </body>
</html>

Main

const { app, BrowserWindow } = require('electron');
const { ipcMain } = require('electron');
const ipc = require('electron').ipcMain;
const path = require('path');
const client = require('discord-rich-presence')('745419354375454901');
 
client.updatePresence({
  state: 'slithering',
  details: '🐍',
  startTimestamp: Date.now(),
  endTimestamp: Date.now() + 1337,
  largeImageKey: 'snek_large',
  smallImageKey: 'snek_small',
  instance: true,
});

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
  app.quit();
}

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });

  // and load the index.html of the app.
  mainWindow.loadFile(path.join(__dirname, 'index.html'));

  // Open the DevTools.
};

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});


ipcMain.on("UpdateRP", stateForRP =>{
  client.updatePresence({
  state: stateForRP,
  details: 'test',
  startTimestamp: Date.now(),
  endTimestamp: Date.now() + 1337,
  largeImageKey: 'logo',
  smallImageKey: 'profilepic',
  instance: true,
});
});

Render

const {ipcRenderer} = require('electron')
const ipc = electron.ipcRenderer;

function updateRP(){
    var stateForRP = "Test";
    ipc.send("UpdateRP", stateForRP);
}


In the provided code, the way the destructuring assignment of the object returned by require ('electron') is handled is quite odd, to say the least...

In renderer :

const {ipcRenderer} = require('electron')
const ipc = electron.ipcRenderer; // The variable *electron* has never been defined!

should be:

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

or:

const { ipcRenderer } = require('electron');
const ipc = ipcRenderer;

or:

const { ipcRenderer: ipc } = require('electron');

Likewise, in main :

const { app, BrowserWindow } = require('electron');
const { ipcMain } = require('electron');
const ipc = require('electron').ipcMain;

can be rewritten without any redundancy as:

const { app, BrowserWindow, ipcMain } = require('electron');
const ipc = ipcMain;

or even more concisely as:

const { app, BrowserWindow, ipcMain: ipc } = require('electron');

[UPDATE]

I just noticed another potential issue in the main process code: the variable mainWindow must be global , so that its value doesn't get garbage-collected... See this post .

Instead of:

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });

  // and load the index.html of the app.
  mainWindow.loadFile(path.join(__dirname, 'index.html'));

  // Open the DevTools.
};

use:

let mainWindow;

const createWindow = () => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });

  // and load the index.html of the app.
  mainWindow.loadFile(path.join(__dirname, 'index.html'));

  // Open the DevTools.
};

It's actually a very simple and easy solution

  1. Ensure the script tag containing the Renderer declaration comes before the html button declaration

This means the script tag with the Renderer code should be within the <title>...</title> block

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM