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

组件卸载后如何关闭WebSocket连接?

解决组件卸载时关闭WebSocket连接的问题

你的代码目前存在几个关键问题,导致无法在组件卸载时正常关闭WebSocket连接:

  1. 没有保存创建的WebSocket实例,卸载时找不到需要关闭的连接对象
  2. timeout未通过useRef存储,存在内存泄漏风险
  3. mountedCount的逻辑冗余,直接用useRef管理socket实例更合理

修改后的代码如下:

import { useEffect, useRef } from 'react';

// ... 其他必要导入

const YourComponent = () => {
  const socketRef = useRef(null);
  const timeoutRef = useRef(null);

  useEffect(() => {
    const connectWebSocket = () => {
      const socketURL = 'socket url here';
      const socket = new WebSocket(socketURL);

      socket.onopen = () => {
        console.log('socket open');
      };

      socket.onclose = (closeEvent) => {
        if (closeEvent.wasClean) return;
        // 重连前清除已有超时任务
        if (timeoutRef.current) clearTimeout(timeoutRef.current);
        timeoutRef.current = setTimeout(() => {
          connectWebSocket();
        }, envVariables.webSocketReconnectionTimeout);
      };

      socket.onerror = () => {
        console.log('error here');
      };

      socket.onmessage = (messageEvent) => {
        console.log('got the message');
      };

      socketRef.current = socket;
    };

    connectWebSocket();

    // 组件卸载时执行清理
    return () => {
      // 清除重连超时任务
      if (timeoutRef.current) clearTimeout(timeoutRef.current);
      // 关闭WebSocket连接
      if (socketRef.current) {
        // 传入正常关闭状态码,避免触发重连逻辑
        socketRef.current.close(1000, 'Component unmounted');
        socketRef.current = null;
      }
    };
  }, [dispatch, userData.userInformation, wss.connectionStatus]);

  // ... 组件其他业务逻辑
};

关键修改说明:

  • 用socketRef存储WebSocket实例,确保在清理函数中能访问到当前连接
  • 用timeoutRef管理重连超时ID,避免内存泄漏,同时在重连前清除旧的超时任务
  • 移除mountedCount,利用useEffect的依赖数组控制连接创建时机,不会重复生成实例
  • 关闭连接时传入状态码1000(正常关闭),让onclose中的wasClean为true,跳过不必要的重连

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:55:32