基于React通用的 WebSocket 钩子 useWebSocket

useWebSocket 钩子封装:

javascript 复制代码
import { useEffect, useRef, useState, useCallback } from 'react';

const useWebSocket = (url: string) => {
  const wsRef = useRef<WebSocket | null>(null); // 用来存储 WebSocket 实例
  const [isConnected, setIsConnected] = useState(false);
  const [lastMessage, setLastMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  // 初始化 WebSocket 连接
  useEffect(() => {
    if (!url) return;

    wsRef.current = new WebSocket(url);

    wsRef.current.onopen = () => {
      console.log(`WebSocket connected to ${url}`);
      setIsConnected(true);
    };

    wsRef.current.onmessage = (event) => {
      setLastMessage(event.data);
    };

    wsRef.current.onerror = (err) => {
      console.error(`WebSocket error on ${url}`, err);
      setError(`Error: ${err}`);
    };

    wsRef.current.onclose = () => {
      console.log(`WebSocket disconnected from ${url}`);
      setIsConnected(false);
    };

    // 组件卸载时,关闭 WebSocket 连接
    return () => {
      wsRef.current?.close();
      wsRef.current = null;
    };
  }, [url]);

  // 发送消息的函数
  const sendMessage = useCallback((message: string) => {
    if (wsRef.current?.readyState === WebSocket.OPEN) {
      wsRef.current.send(message);
    } else {
      console.warn(`WebSocket is not open. Unable to send message: ${message}`);
    }
  }, []);

  return {
    isConnected,
    lastMessage,
    sendMessage,
    error,
  };
};

export default useWebSocket;

使用示例:

你可以通过 useWebSocket 钩子在组件中使用 WebSocket 功能,轻松地连接、接收消息和发送消息。

javascript 复制代码
import React, { useEffect } from 'react';
import useWebSocket from './useWebSocket';

const WebSocketComponent = () => {
  const { isConnected, lastMessage, sendMessage, error } = useWebSocket('ws://example.com/first');

  useEffect(() => {
    // WebSocket 连接后发送一条消息
    if (isConnected) {
      sendMessage('Hello, WebSocket!');
    }
  }, [isConnected, sendMessage]);

  // 每次 lastMessage 更新时,打印接收到的数据
  useEffect(() => {
    if (lastMessage) {
      console.log('Received message:', lastMessage);
    }
  }, [lastMessage]);

  return (
    <div>
      <h1>WebSocket 实时数据</h1>
      <p>连接状态: {isConnected ? '已连接' : '未连接'}</p>
      <p>最近消息: {lastMessage || '暂未收到消息'}</p>
      {error && <p>错误: {error}</p>}
      <button onClick={() => sendMessage('Another message')}>发送消息</button>
    </div>
  );
};

export default WebSocketComponent;
相关推荐
光影少年12 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
Rattenking17 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试3 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc4 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9154 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼5 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
小牛itbull6 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress