Как обновить состояние реакции при использовании контекстного моста/предварительной загрузки в приложении electron

#reactjs #electron #ipcrenderer #ipcmain

Вопрос:

У меня есть электронное приложение, которое использует react. Я использую контекстный мост в preload.js. Я хотел бы передать переменную из app.js через мост к функции в основном процессе; которая возвращает значение мосту и обратно в app.js где он каким-то образом обновит состояние и вызовет повторный вызов. Следующий код работает до момента получения состояния для обновления. Я не понимаю, как получить переменную из preload.js чтобы app.js? Мой, надеюсь, временный взлом состоит в том, чтобы установить localstorage из предварительной загрузки и вызвать функцию setTimeout для отслеживания изменений в определенных переменных. Я знаю, что это менее чем интересный подход. Код здесь:

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

Ответ №1:

Вы можете использовать вызов ipcRenderer и дескриптор ipcMain:

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);
 

В документации: https://www.electronjs.org/docs/api/ipc-renderer#ipcrendererinvokechannel-args

Комментарии:

1. Спасибо вам за ваш ответ.

2. Хорошо, я приношу извинения за преждевременное согласие. Я попробовал ваш код, и я все еще не знаю, как вернуться из preload.js чтобы app.js. Я уверен, что это проблема синтаксиса, или я не понимаю отдачу от предварительной загрузки. Если у вас есть время, не могли бы вы взглянуть на код, который я написал ниже. Спасибо

3. Извините, что я не проверил код, я проверю его и посмотрю, смогу ли я это исправить. Возможно, я ошибся, потому что этот метод хорошо работал для меня в прошлом.

4. Ладно, я наконец-то возвращаюсь к этому. Этот синтаксис работает для меня, и я отмечаю ваш ответ как правильный.

Ответ №2:

Хорошо, я приношу извинения за то, что разместил еще один вопрос в разделе ответов, я не понимаю, как форматировать код в ответе на комментарий.

Этот код все равно не вернется в app.js:

 app.js    

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

возвращает разрешение, не дожидаясь возврата от preload.js. Вот код из preload.js

 preload.js    

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

Комментарии:

1. Я обновил свой ответ, чтобы быть более ясным. Кстати, в preload.js файл является избыточным, использование createSpreadsheetFiles: (name) => ipcRenderer.invoke('gCreateSpreadSheetFile-invoke', name); будет иметь тот же эффект, и в app.js вы должны использовать window.electron.g... .