I have an Electron app (electron v23) that reads a config file and determines some configurations. I have a separate react project, my Electron window opens the URL for the react app once the configuration has been decided.
The Electron app needs to put the config object in the React app’s window object (renderer’s window object) before any of the client code can execute.
I tried a few methods, but none seem to work:
Approach 1:
const validChannels = ['something'];
const { contextBridge, ipcRenderer } = require("electron");
const { getConfig } = require("./config");
contextBridge.exposeInMainWorld("electron", {
getConfig: () => {
return getConfig();
},
send: (channel, data) => {
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender` and is a security risk
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
},
});
Here is how I am opening the window for the same:
const win = new BrowserWindow({
width: 1600,
height: 1000,
webPreferences: {
nodeIntegration: false,
devTools: true,
contextIsolation: true,
sandbox: false,
preload: path.join(__dirname, "preload.js"),
}
}
});
When I use this approach I get an error at some internal script electron.app.isPackaged
cannot be accessed as electron.app
is undefined. I tried a few other options like setting nodeIntegration: true
but nothing worked so far.
Approach 2
win.webContents.on("did-finish-load", () => {
win.webContents.executeJavaScript(`window.__configFromElectron = ${JSON.stringify(getConfig())};`);
});
This approach does set the variable __configFromElectron
but this is set much later in the code. The initialization scripts in React that need this config receive an undefined
, but much later they get the actual config. I tried different options here like did-start-loading
and dom-ready
.None of them make it so that the variable is loaded first.
I tried a few other approaches where I try to block the React render of components until this variable is available, but this config is expected in a singleton and it is getting evaluated beforehand, even if I block the render process. (I used methods like ipcMain.handle
and ipcRenderer.invoke
) but none of these solutions are elegant.
Doing a refactor of the React app such that this config is async
and all the dependencies have to await
is a very big change. What is the right way to go about this?
2
Answers
You can do something like this in the your Approach 2.
You need to ensure that the config object is set before any of the code that depends on it runs. You could use a Promise to ensure that the config object is set before other code executes.
This approach will ensure that the config object is set before any code that depends on it runs, but it does require modifying your React app to use an async initialization method.
There are a few ways to do this, but my preferred way is to use the
BrowserWindow
‘sadditionalArguments
option.Note: this method can only send strings
Main process
Preload script