How To Communicate Between Two Electron Windows

I am working on a little Electron app for fun. This app mostly runs in a main window but on certain user interactions it opens a second little window that waits for user input.

Kahlil Lechelt
3 min readNov 10, 2016

Once the user is done and the second window is closed it needs to send whatever the user entered back to the main window.

From the Electron docs it didn’t immediately become clear to me how to implement the communication between the two windows, but after some trial and error I figured it out.

An Electron app always comes with a main process that starts Electron and opens a main window or starts a tray icon app.

In my case it opens a main window. That window is a browser window, it runs in the renderer process and loads all the HTML, CSS and JavaScript needed for the application.

This is the code the creates the window and starts a listener on the close event in order to close it again:

const path = require('path');
const BrowserWindow = electron.BrowserWindow;

app.on('ready',() => {
// Create the browser window.
const mainWindow = new BrowserWindow(config);
const filePath = path.join(
'file://',
process.cwd(),
'index.html'
);
// and load the index.html of the app.
mainWindow.loadURL(filePath);
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object,
// usually you would store windows
// in an array if your app supports
// multi windows, this is the time
// when you should delete the
// corresponding element.
mainWindow = null;
});
});

In the JavaScript file that gets loaded by the main application window I can now listen to an event and open a second window like this:

const BrowserWindow = electron.BrowserWindow;
let win = new BrowserWindow({width: 400, height: 275});

That window has its own process with its own HTML, CSS and JavaScript. If I want I can send a message to that window from the main window with the webContents API when it has finished loading:

win.webContents.on('did-finish-load', () => {
win.webContents.send('message', 'Hello second window!');
});

In the JavaScript for that second window you can receive that message with the ElectronipcRenderer module:

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

ipc.on('message', (event, message) => {
console.log(message); // logs out "Hello second window!"
})

When you are ready to send a message from the second window to the main window you have to send it via the main process. You can’t send a message back to the main window directly. I assume this is in order to avoid a circular dependency.

Use the ElectronipcRenderer module from the second window to sent a message to the main process:

ipc.send('reply', `This message goes back to the main window.`);

In main.js file you then can receive the message via the ipcMain module by listening to the event name specified in the send function above. In this case “reply”:

ipc.on('reply', (event, message) => console.log(message));
// => This message goes back to the main window.

The main process can then send a message via mainWindow.webContents.send('reply’, message) to the renderer process.

In the main renderer process you then can receive that message by listening to the “reply”-event on the ipcRenderer module:

const ipc = require('electron').ipcRenderer;
ipc.on('reply', m => console.log(m));

There you have it: communication between two Electron windows.

I have a working demo of this on Github. Follow the instructions in the Readme to run it.

--

--