如何在Electron(Next.js/React)中实现WebSocket客户端?
在Nextron(Next.js + Electron)中正确使用WebSocket的位置
你遇到的问题根源是:Next.js的服务端渲染(SSR)机制会在服务端执行组件顶层代码,而服务端环境没有浏览器提供的WebSocket API,直接在_app.tsx组件顶层创建实例会触发报错。Electron的渲染进程本身支持WebSocket,但必须确保代码只在客户端环境执行。
正确的实现方式
将WebSocket的初始化逻辑放到useEffect钩子中,并使用useRef持久化实例,避免组件重渲染时重复创建连接:
import React from 'react'; import Head from 'next/head'; import { ThemeProvider } from '@material-ui/core/styles'; import CssBaseline from '@material-ui/core/CssBaseline'; import { theme } from '../lib/theme'; import type { AppProps } from 'next/app'; export default function (props: AppProps) { const { Component, pageProps } = props; // 用useRef持久化WebSocket实例,避免组件重渲染时重复创建 const wsRef = React.useRef<WebSocket | null>(null); React.useEffect(() => { // 仅在客户端环境初始化WebSocket if (typeof window !== 'undefined') { const ws = new WebSocket("ws://192.168.100.8:8081/"); wsRef.current = ws; // 可以在这里添加WebSocket的事件监听 ws.onopen = () => { console.log("WebSocket连接已建立"); }; ws.onmessage = (event) => { console.log("收到WebSocket消息:", event.data); }; ws.onerror = (error) => { console.error("WebSocket错误:", error); }; ws.onclose = () => { console.log("WebSocket连接已关闭"); }; } // 组件卸载时关闭WebSocket连接,防止内存泄漏 return () => { if (wsRef.current) { wsRef.current.close(); } }; }, []); // 空依赖数组确保只执行一次 React.useEffect(() => { const jssStyles = document.querySelector('#jss-server-side'); if (jssStyles) { jssStyles.parentElement.removeChild(jssStyles); } }, []); return ( <React.Fragment> <Head> <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" /> </Head> <ThemeProvider theme={theme}> <CssBaseline /> <Component {...pageProps} /> </ThemeProvider> </React.Fragment> ); }
关键注意点
- 客户端环境判断:通过
typeof window !== 'undefined'确保代码只在浏览器/Electron渲染进程执行,避开服务端渲染阶段。 - 实例持久化:使用
useRef存储WebSocket实例,保证组件重渲染时不会重新创建连接。 - 生命周期清理:在
useEffect的返回函数中关闭连接,避免组件卸载后残留无效连接。 - Electron安全策略:如果连接失败,检查Electron的
contentSecurityPolicy配置,确保允许连接到目标WebSocket服务器地址。
扩展方案
如果需要在多个组件中使用WebSocket,可以将其封装为自定义Hook或者React Context,实现全局状态管理和事件分发,方便各组件共享连接状态和消息。
内容的提问来源于stack exchange,提问作者DennyHiu
相关产品推荐
相关产品推荐

