Electron ipcRenderer 监听器在 React 组件中未触发

问题描述 投票:0回答:2

我有一个按钮应该触发所有窗口执行操作,播放媒体。

我在主进程中有一个 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 之间重叠的通道名称可能会导致问题,但我添加了一个新的通道名称进行测试,但仍然无法让侦听器触发。

electron electron-react-boilerplate
2个回答
0
投票

自从提出这个问题以来,电子反应样板中的示例 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);
  };
},
...

0
投票

@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 秒触发一次(出于测试目的),但永远不会在组件内部触发。

如果你还有的话,介意分享一下你的代码吗?

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.