首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从React组件创建的电子中删除`preload.js`中的事件监听器

从React组件创建的电子中删除`preload.js`中的事件监听器
EN

Stack Overflow用户
提问于 2021-08-26 14:21:47
回答 1查看 1.1K关注 0票数 1

我使用带有React 17的电子13。我将nodeIntegration设置为false,contextIsolation设置为true,因此我使用preload.js文件公开一个API,以在主进程和呈现程序进程之间进行通信。

我必须使用此API在React组件中侦听IPC消息。然而,每次我的组件被挂载(或重新呈现)时,电子都会创建一个新的IPC事件侦听器,从而导致内存泄漏。

preload.js

代码语言:javascript
运行
复制
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('api', {
    send: (channel, data) => {
        // Whitelist channels
        let validChannels = ['toMain'];
        if (validChannels.includes(channel)) {
            ipcRenderer.send(channel, data);
        }
    },
    receive: (channel, func) => {
        let validChannels = ['fromMain'];
        if (validChannels.includes(channel)) {
            // Deliberately strip event as it includes `sender`
            ipcRenderer.on(channel, (event, ...args) => func(...args));
        }
    }
});

ReactComponent.js

代码语言:javascript
运行
复制
import { useEffect, useRef } from 'react';

const ReactComponent = () => {
    const _isMounted = useRef(true);

    const exampleFunction = () => {
        window.api.send('toMain');
    };

    window.api.receive('fromMain', function (data) {
        if (_isMounted.current) {
            // Process `data`...
        }
    });

    useEffect(() => {
        exampleFunction();

        // Another IPC call
        window.api.send('toMain', ['example']);
        window.api.receive('fromMain', function (data) {
            // Process `data`...
        });

        return () => {
            _isMounted.current = false;
            // Somehow I should remove the IPC event listeners here,
            // but I don't know how, since (I think) they are created 
            // in the `preload.js` file...
        };
    }, []);


    return (
        // JSX
    );
};

export default ReactComponent;

如何取消注册通过window.api.receive()创建的事件侦听器

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-26 17:03:26

GitHub上的这个问题精确地解决了这些问题。简而言之,在preload.js中创建的事件侦听器被分配给一个变量,以便脚本可以返回一个回调以删除事件侦听器。

下面是如何执行此操作的示例:

preload.js

代码语言:javascript
运行
复制
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('api', {
    // ...
    receive: (channel, func) => {
        let validChannels = ['fromMain'];
        if (validChannels.includes(channel)) {
            // Deliberately strip event as it includes `sender`
            const subscription = (event, ...args) => func(...args);
            ipcRenderer.on(channel, subscription);
            return () => {
                ipcRenderer.removeListener(channel, subscription);
            };
        }
    },
});

ReactComponent.js

代码语言:javascript
运行
复制
import { useEffect } from 'react';

const ReactComponent = () => {

    const onEvent = (data) => {
        // Process `data`...
    };

    useEffect(() => {
        const removeEventListener = window.api.receive('fromMain', (data) => onEvent(data));

        // ...

        return () => {
            removeEventListener();
        };
    }, []);

    return (
        // JSX
    ); 
};

export default ReactComponent;
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68940343

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档