How to update react state when using contextBridge/preload in electron app

1.3k views Asked by At

I have an electron application that is using react. I am using the contextBridge in preload.js. I would like to pass a variable from app.js through the bridge to a function in the main process; which returns a value to the bridge and back to app.js where it will somehow update state and trigger a rerender. The following code is working up to the point of getting state to update. I do not understand how to get a variable from preload.js to app.js? My hopefully-temporary hack is to set localstorage from the preload and call a setTimeout function to watch for changes on specific variables. I know this is a less than interesting approach. Code is here:

app.js -

async function createSpreadsheet() {
  let x = await electron.google.createSpreadsheetFiles(sheetFileName)
}

preload.js -

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

contextBridge.exposeInMainWorld('electron', {
  google: {
    createSpreadsheetFiles(name) {
      ipcRenderer.send('gCreateSpreadSheetFile', name);
      let x = ipcRenderer.on('gCreateSpreadSheetFile-return', function (event, arg) {
      })
      return x
    },
  },
})

main.js -

  ipcMain.on('gCreateSpreadSheetFile', (event, name) => {
    async function all() {
      let resp = await g.createSheetFile(name, win)
      event.sender.send('gCreateSpreadSheetFile-return', resp)
    }
    all()
  })
2

There are 2 answers

3
Autumn On BEST ANSWER

You can use ipcRenderer invoke and ipcMain handle:

preload.js

contextBridge.exposeInMainWorld('electron', {
  google: {
    createSpreadsheetFiles: (name) => ipcRenderer.invoke('gCreateSpreadSheetFile-invoke', name),
  },
});

main.js

ipcMain.handle('gCreateSpreadSheetFile-invoke', (event, name) => {
  return 'value';
});

renderer

window.electron.google.createSpreadsheetFiles(spreadSheetName).then((value) => {
  console.log(value);
});
// or
var value = await window.electron.google.createSpreadsheetFiles(spreadSheetName);

On the documentation: https://www.electronjs.org/docs/api/ipc-renderer#ipcrendererinvokechannel-args

1
DMonde On

Ok, I apologize for posting another question in the answer section, I do not understand how to format code in the comment response.

This code still will not return to app.js:

app.js    

const res = await electron.g.createSpreadsheetFiles(sheetFileName)
        console.log(res) // prints undefined, before code is excecuted

returns the res without waiting for a return from preload.js. Here is the code from preload.js

preload.js    

g: {
        createSpreadsheetFiles(name) {
          (async () => {
            const result = await ipcRenderer.invoke('gCreateSpreadSheetFile-invoke',  name);
            return result; 
          })();
      }