如何使用contextBridge从Electron main.js调用React组件函数



正如标题所述,我想从Electron main.js文件中调用一个在React组件中定义的函数。我知道如何用另一种方式来实现,例如,用户单击一个按钮,它调用main.js中的一个函数,然后返回React组件。我需要相反,main.js调用React函数,然后将结果返回给main。

我不能简单地拥有main.js中的所有功能,因为我不能从React向main传递DOM对象(这导致了错误"object cannot be clone"(。因此,我认为将请求发送到React,让我的应用程序的React端完成这些操作,然后将结果字符串返回到main应该不会太难。

我在这里发现了许多其他类似的帖子,其中提供了各种解决方案,但没有一个专门针对这个问题#1公开了ipcRenderer,这是一种糟糕的安全做法,我负担不起#2和#3只针对普通的Javascript进行了解释,而不是React组件。虽然#4处理React,但它不处理Electron,它是为React类设计的(我使用的是功能组件(。

我的尝试看起来像这样一团糟:

const [mounted, setMounted] = useState(false)
if(!mounted){
window.reactFunction = myFunction;
}

useEffect(() =>{
setMounted(true)
},[])
window.electron.receive("fromMain", async () => {
return myFunction();
});
async function myFunction()
{       
return "result";
}

但是,该函数在渲染期间被调用,而不是由contextBridge调用。这是我的预加载.js:

contextBridge.exposeInMainWorld('electron', {

receive: async (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
return await ipcRenderer.on("fromMain", (event, ...args) => func(...args));
}
}
});

由于某些原因,preload.js脚本没有执行。这是main.js:

const result = window.webContents.send('fromMain');

我还发现了这次讨论,其中明确了与直接调用ipcRenderer相关的安全问题,因此我想使用contextBridge(无论如何,我已经在使用它来调用React的主要函数(。这也是我的预加载.js代码的来源。但这个例子也没有使用React。

这可能吗?还是我应该换一种方式来解决这个问题?

看起来我在这行打错了:

return await ipcRenderer.on("fromMain", (event, ...args) => func(...args));

在这一行中,我将返回函数,因此函数本身不会被调用。删除";返回";它会起作用的"Await";似乎没有什么区别。

然而,一旦您调用了该函数,它实际上就不能返回任何内容。因此,您需要从渲染器再次调用main,如下所示:

window.electron.receive("fromMain", async () => {
const returnValue = await myFunction();
window.electron.sendReturnValue(returnValue);
});
async function myFunction()
{       
return "result";
}

除非有更好的方法,但这暂时解决了我的问题,并有望帮助其他人。

最新更新