我有一个按钮应该触发所有窗口执行操作,播放媒体。
我在主进程中有一个 MediaProvider 类,用于处理媒体 IPC 通道的所有通信(为简洁起见,已截断)。该类在
main.ts
中初始化。
export default class MediaProvider {
public constructor() {
ipcMain.on(MEDIA_CHANNELS.PLAY, async (e: Electron.IpcMainInvokeEvent) => {
console.log('PLAY handler in ipcMain');
const result = await this.playMedia();
return result;
});
...
}
private playMedia = () => {
BrowserWindow.getAllWindows().forEach(window => {
console.log(`Sending PLAY command to window ${window.id}.`)
window.webContents.send(MEDIA_CHANNELS.PLAY);
});
}
...
}
我的主要组件在单击播放按钮时调用此函数:
window.electron.ipcRenderer.send(MEDIA_CHANNELS.PLAY);
这会正确触发我的
ipcMain
处理程序。
在另一个功能性 React 组件中,我有以下内容:
useEffect(() => {
initListeners();
}, []);
const initListeners = () => {
window.electron.ipcRenderer.on(MEDIA_CHANNELS.PLAY, (_) => {
console.log('PLAY in component');
playMedia();
});
...
}
我的
preload.ts
只是按原样公开 ipcRenderer 方法:
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: {
send: ipcRenderer.send,
on: ipcRenderer.on,
invoke: ipcRenderer.invoke
},
});
监听器永远不会被触发,永远不会有“在组件中播放”日志。是什么导致我的监听器无法触发?
我尝试将上述组件重写为类组件与功能组件,但它没有解决任何问题。我还认为 ipcMain 和 ipcRenderer 之间重叠的通道名称可能会导致问题,但我添加了一个新的通道名称进行测试,但仍然无法让侦听器触发。
自从提出这个问题以来,电子反应样板中的示例 preload.ts 已更新。 https://github.com/electron-react-boilerplate/electron-react-boilerplate/blob/main/src/main/preload.ts
在完全匹配
.on(...)
的示例后,并且无需更改任何其他内容,我的处理程序现在可以工作了。
...,
on(channel: MEDIA_CHANNELS, func: (...args: unknown[]) => void) {
const subscription = (_event: IpcRendererEvent, ...args: unknown[]) =>
func(...args);
ipcRenderer.on(channel, subscription);
return () => {
ipcRenderer.removeListener(channel, subscription);
};
},
...
@Tristan 我知道这已经一年多了,但我在这里遇到了同样的问题。我有一个全新的
electron-vite
项目正在运行 React 应用程序。
样板已经设置了
window.electron
API,因此我可以访问 window.electron.ipcRenderer.on(...)
。
应用程序.tsx
function App() {
const updateAvailable: string | null = null
useEffect(() => {
const callback = (...args: unknown[]): void => {
console.log('args', args)
// set updateAvailable
}
const removeListener = window.electron.ipcRenderer.on('update-downloaded', callback)
return () => {
removeListener()
}
})
return (
<div>{updateAvailable}</div>
)
}
main.ts:
updater.autoUpdater.on('update-downloaded', (info) => {
console.log('AutoUpdater::update-downloaded')
mainWindow?.webContents.send('update-downloaded', info)
setTimeout(() => updater.autoUpdater.checkForUpdatesAndNotify(), 1000 * delayBeforeNextCheck)
})
来自主线程的事件每 10 秒触发一次(出于测试目的),但永远不会在组件内部触发。
如果你还有的话,介意分享一下你的代码吗?
谢谢!