我有一个简单的React组件,它在安装时在IPC中注册了一个新的侦听器,在卸载时应该删除该侦听器。问题是,由于某种原因,我的侦听器引用与注册它时使用的引用不匹配,我不知道为什么。
React组件简化代码
import React, { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useAppDispatch } from '../../redux/storeHooks';
import { setAuthToken } from './state/authSlice';
import { LocationAuthState } from '../common/RequireAuth/types';
export default () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const navigatedFrom = useNavigatedFrom();
useEffect(() => {
const userLoggedInHandler = (_: Electron.IpcRendererEvent, loginToken: string) => {
dispatch(setAuthToken({ token: loginToken }));
navigate(navigatedFrom, { replace: true });
};
const ref1 = userLoggedInHandler;
window.ipc.startLoginListenerHttpServer();
window.ipc.userLoggedIn(userLoggedInHandler);
return () => {
const theSame = ref1 === userLoggedInHandler;
console.log(theSame); // this logs true
window.ipc.stopLoginListenerHttpServer();
window.ipc.removeUserLoggedInListener(userLoggedInHandler);
};
}, []);
return (
<div>
{`Waiting for login result...`}
</div>
);
};
function useNavigatedFrom() {
const location = useLocation();
const locationState = location.state as LocationAuthState;
return locationState?.from?.pathname || `/`;
}
预加载. js
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import IpcEvent from '../ipcEvent';
let originalHandlerReference: any;
contextBridge.exposeInMainWorld(`ipc`, {
startLoginListenerHttpServer: () => ipcRenderer.send(IpcEvent.StartLoginListenerHttpServer),
stopLoginListenerHttpServer: () => ipcRenderer.send(IpcEvent.StopLoginListenerHttpServer),
userLoggedIn: (handler: (event: IpcRendererEvent, loginToken: string) => void) => {
originalHandlerReference = handler;
ipcRenderer.on(IpcEvent.UserLoggedIn, handler);
},
removeUserLoggedInListener: (handler: (event: IpcRendererEvent, loginToken: string) => void) => {
const countBefore = ipcRenderer.listenerCount(IpcEvent.UserLoggedIn); // 1
const theSame = originalHandlerReference === handler; // false
const theSameAsOriginal = originalHandlerReference === ipcRenderer.listeners(IpcEvent.UserLoggedIn)[0]; // true
const theSameAsCurrentHandler = handler === ipcRenderer.listeners(IpcEvent.UserLoggedIn)[0]; // false
ipcRenderer.off(IpcEvent.UserLoggedIn, handler);
const countAfter = ipcRenderer.listenerCount(IpcEvent.UserLoggedIn); // 1
},
});
1条答案
按热度按时间von4xj4u1#
看看
contextBridge
上的电子文档,我们可以看到“正常”渲染器进程和执行预加载脚本的隔离部分之间的通信是双向 * 复制 * 的。这意味着在渲染器和预加载上下文之间传递的任何两个对象(反之亦然)都不会 * 完全 * 相同。因此,您不能使用
===
来检查传递给预加载脚本的两个函数是否相等。我建议为每个注册的侦听器生成一个ID,将其传递给调用代码,并将其存储在实际函数旁边的Map中。这样,组件就可以调用您的“unmount”函数,提供注册其侦听器时提供的ID。预加载脚本将查找给定ID的处理程序函数并将其从IPC通道中移除。