reactjselectronipcrendereripcmain

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


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()
  })

Solution

  • 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