React类组件中在哪里声明websocket连接可访问实例以便关闭后重开
错误原因说明
你遇到的'ws' is not defined no-undef是ESLint的语法校验报错,不属于代码运行错误。核心原因有两个:要么是拼写错误(你贴的第二种写法里class误写为lass),要么是ESLint没有配置浏览器环境,识别不了WebSocket这个浏览器全局API。
推荐实现方案
不要把WebSocket实例存在state里,它不需要触发视图渲染,直接存在类实例属性上即可,完全可以满足「连接声明和开启逻辑分离、新开连接前关闭旧连接」的需求,完整实现如下:
import React, { Component } from 'react'; class App extends Component { // 声明ws实例属性,初始值为空 ws = null; state = { // 仅存放需要触发视图更新的状态,ws实例不需要存在这里 }; // 单独封装开启连接的方法 openWs = (connectUrl) => { // 新开连接前先关闭已有连接 if (this.ws) { this.closeWs(); } // 新建ws实例挂载到实例属性上 this.ws = new WebSocket(connectUrl); // 绑定连接事件回调 this.ws.onopen = () => { console.log('连接成功'); }; this.ws.onmessage = (e) => { console.log('收到消息:', e.data); }; this.ws.onerror = (err) => { console.error('连接出错:', err); }; this.ws.onclose = () => { console.log('连接已关闭'); this.ws = null; }; }; // 单独封装关闭连接的方法 closeWs = () => { if (this.ws) { // 清空事件监听避免内存泄漏 this.ws.onopen = null; this.ws.onmessage = null; this.ws.onerror = null; this.ws.close(); this.ws = null; } }; // 组件卸载时强制关闭连接,避免内存泄漏 componentWillUnmount() { this.closeWs(); } render() { // 任意类方法、渲染逻辑里都可以通过this.ws访问当前连接实例 return ( <div> <button onClick={() => this.openWs("wss://ws-feed.pro.coinbase.com")}>开启连接</button> <button onClick={this.closeWs}>关闭连接</button> </div> ) } } export default App;
校验报错修复方案
如果还是报no-undef错误,可以任选一种方式修复:
- 在项目ESLint配置文件里添加
env: { browser: true },让ESLint识别浏览器全局API - 在当前文件顶部加注释
/* global WebSocket */,单独声明WebSocket是全局变量
全局声明方案的注意点
如果一定要用全局声明的方式,不要直接在import同级初始化连接,改为先声明变量,再在需要的时候初始化:
// 全局仅声明变量,不直接初始化 let globalWs = null; class App extends Component { openWs = () => { if (globalWs) { // 关闭逻辑和实例属性方案一致 } globalWs = new WebSocket("wss://ws-feed.pro.coinbase.com"); } }
不推荐全局声明的方式,单页应用场景下全局变量不会随组件销毁自动清空,容易出现内存泄漏、多页面复用连接冲突的问题。
内容的提问来源于stack exchange,提问作者Andrew_Ciavega
相关产品推荐
相关产品推荐

