You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Electron向React应用传递变量数据并更新UI

Web React应用迁移Electron后的数据传递问题

问题背景

将基于Web的React应用迁移到Electron GUI并保留React框架,原本通过Express+Socket.IO实现前后端数据通信,现在改用Electron的preload/renderer进程架构。目前已能在render.js中获取主进程返回的数据,但不知道如何将数据传递给dash.jsx以更新GUI。


旧数据传输方式

server.js(后端)

// Server part
var app = express();

app.use('/', express.static(path.join(__dirname, 'public')));
var port = 8090
var server = app.listen(port);
console.log('Server listening on port ' + port);

// Socket.IO part
var io = require('socket.io')(server);

io.on('connection', function (socket) {
    console.log('New client connected!');

    //send data to client
    setInterval(function () {

        // Change values so you can see it go up when developing
        if (process.env.NODE_ENV === "development") {
            //do something with the data
        }
        socket.emit('ecuData', { send the data });
    }, 100);
});

dash.jsx(前端React组件)

componentDidMount: function () {
    this.socket = io();
    this.socket.on('ecuData', function (data) {
        this.setState({ rpm: data.rpm });
        this.setState({ coolantTemp: data.coolantTemp });
        this.setState({ fuelLevel: data.fuelLevel })
        this.setState({ odo: data.odo })
        this.setState({ drive: data.drive })
        this.setState({ amp: data.amp })
        this.setState({ dte: data.dte })
    });
},

新数据传输方式

render.js(渲染进程)

document.addEventListener('DOMContentLoaded', () => {
    setInterval(async () => {    
        const data = await electronAPI.getDashData();
    }, 100);
})

preload.js(预加载脚本)

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
    getDashData: (data) => ipcRenderer.invoke('getData', data)
})

gui.js(主进程)

const createWindows = (win, page) => {
    win = new BrowserWindow({
        width: 1024,
        height: 600,
        resizable: false,
        fullscreen: true,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'),
        },
    });
    if(page == "dash.html"){
        ipcMain.handle('getData', (req, data) => {
            var dashData = {
                rpm: rpm,
                carSpeed: carSpeed,
                coolantTemp: coolantTemp,
                fuelLevel: fuelLevel,
                odo: odo,
                drive: drive,
                amp: amp,
                dte: dte,
                onoffLights: onoffLights
            }
            return (dashData);
        })
    }
    win.loadFile(page)
};

function updateData() {
    // Change values so you can see it go up when developing
    if (process.env.NODE_ENV === "development") {
        setInterval(() => {
            //do something with the data
        }, 100)
    }
}
app.whenReady().then(() => {
    createWindows(leftWindow, "dash.html");
    //createWindows(rightWindow, "controls.html");
    updateData()
});

解决方案

方法1:React组件内直接调用electronAPI

删除单独的render.js,直接在React组件的生命周期钩子或useEffect中发起请求并更新状态:

// 类组件版本
componentDidMount() {
    this.interval = setInterval(async () => {
        const data = await window.electronAPI.getDashData();
        this.setState({
            rpm: data.rpm,
            coolantTemp: data.coolantTemp,
            fuelLevel: data.fuelLevel,
            odo: data.odo,
            drive: data.drive,
            amp: data.amp,
            dte: data.dte,
            carSpeed: data.carSpeed,
            onoffLights: data.onoffLights
        });
    }, 100);
}

componentWillUnmount() {
    clearInterval(this.interval); // 组件卸载时清理定时器,避免内存泄漏
}

// 函数组件版本
useEffect(() => {
    const interval = setInterval(async () => {
        const data = await window.electronAPI.getDashData();
        setState(prev => ({ ...prev, ...data })); // 合并更新状态
    }, 100);
    
    return () => clearInterval(interval);
}, []);

方法2:通过全局事件传递数据(保留render.js)

在render.js中拿到数据后触发自定义事件,让React组件监听:

// render.js
document.addEventListener('DOMContentLoaded', () => {
    setInterval(async () => {    
        const data = await electronAPI.getDashData();
        // 触发自定义事件传递数据
        document.dispatchEvent(new CustomEvent('dashDataUpdate', { detail: data }));
    }, 100);
})

// dash.jsx 类组件
componentDidMount() {
    this.handleDataUpdate = (e) => {
        const data = e.detail;
        this.setState({
            rpm: data.rpm,
            coolantTemp: data.coolantTemp,
            // ...其他字段
        });
    };
    document.addEventListener('dashDataUpdate', this.handleDataUpdate);
}

componentWillUnmount() {
    document.removeEventListener('dashDataUpdate', this.handleDataUpdate);
}

// dash.jsx 函数组件
useEffect(() => {
    const handleDataUpdate = (e) => {
        const data = e.detail;
        setState(prev => ({ ...prev, ...data }));
    };
    document.addEventListener('dashDataUpdate', handleDataUpdate);
    return () => document.removeEventListener('dashDataUpdate', handleDataUpdate);
}, []);

关键注意事项

  • 务必在组件卸载时清除定时器,避免内存泄漏
  • 用状态合并的方式一次性更新所有字段,比多次调用setState更高效

内容的提问来源于stack exchange,提问作者Grez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:20:20