useWebSocket

Tags:
这个 Hook 自 v1.7.0 版本起可用。

一个简化 WebSocket 使用的 React Hook,是原生 WebSocket API 的包装,支持自动重连、心跳包、消息队列等功能。

场景

  • 持久连接场景: 用于需要与服务器保持长时间连接的场景,如即时通讯
  • 实时数据更新: 实现股票、交易等实时数据的推送更新
  • 游戏开发中的实时交互: 在多人在线游戏中同步玩家状态、游戏进度
  • 心跳检测与自动重连: 确保连接稳定,自动处理连接中断和重连

演示

源码

WS URL as Params

Edit the WS URL in the input field below and it will automatically reconnect when the URL changes.

WS URL:
wss://echo.websocket.org
Status:
Closed
No message received yet.

Programmatic WS URL

Edit the WS URL in the input field below and click the "Connect" button to establish a connection.

WS URL:
Status:
Closed
No message received yet.

用法

const ws = useWebSocket(wsUrl, options)

const ws = useWebSocket('wss://echo.websocket.org', {
  // 默认为 false,配置为 true 时使用默认心跳配置
  // 也可以配置为 { interval: 5_000, message: 'ping', responseMessage: 'pong', responseTimeout: 1_000 }
  heartbeat: true, 

  // 默认为 true,断线时自动重连,配置为 false 时不进行重连
  // 也可以配置为 { count: 3, interval: 1_000 } (默认配置)
  reconnect: true,

  // 过滤掉服务端响应的心跳消息
  // filter: (event) => event.data === 'ping',

  // 生命周期回调
  onOpen() {
    console.log('WebSocket 连接已打开')
  },
  onMessage(message) {
    console.log('收到消息', message)
  },
  onError(error) {
    console.error('WebSocket 连接发生错误', error)
  },
  onClose(event) {
    console.log('WebSocket 连接已关闭', event)
  },
})

// ws.readyState // => 0 (CONNECTING), 1 (OPEN), 2 (CLOSING), 3 (CLOSED)

// ws.send(data)
// ws.close()
// ws.open()

// ws.ws // => WebSocket 实例

源码

点击下方链接跳转 GitHub 查看源代码。

API

const ws = useWebSocket(wsUrl, options)

// 或者
const ws = useWebSocket(options)
ws.open(wsUrl)

WsUrl 连接字符串

一个 WebSocket URL 字符串。

Options 选项

export type UseWebSocketSendable = string | ArrayBufferLike | Blob | ArrayBufferView

export interface UseWebSocketOptionsHeartbeat {
  /**
   * 发送的心跳消息。
   *
   * @defaultValue 'ping'
   */
  message?: UseWebSocketSendable
  /**
   * 发送心跳消息的间隔时间。
   *
   * @defaultValue 1_000
   */
  interval?: number
  /**
   * 服务端响应超时时间。
   *
   * @defaultValue 1_000
   */
  responseTimeout?: number
  /**
   * 被认作是服务端响应心跳包的消息,默认为 true,即只要有消息返回就认为是心跳包响应(被认为服务端存活)
   * 
   * 可以传入一个消息字符串,或者一个函数,函数返回 true 时认为是心跳包响应,需要配合 responseTimeout 使用,当超时时会认为服务端已断开。
   *
   * @defaultValue true
   */
  responseMessage?: true | UseWebSocketSendable | ((data: UseWebSocketSendable) => boolean)
}

export interface UseWebSocketOptionsReconnect {
  /**
   * 重连的次数,可以为重试次数或者返回 boolean 的函数,函数返回 true 时继续重连,返回 false 时停止重连。
   * 
   * @defaultValue () => true
   */
  count?: number | (() => boolean)
  /**
   * 重连的间隔时间。
   * 
   * @defaultValue 1_000
   */
  interval?: number
  /**
   * 当重连失败时的回调函数。
   */
  onFailed?: (event: CloseEvent, ws: WebSocket) => void
}

export interface UseWebSocketOptions {
  /**
   * 当 WebSocket 的 open 事件被触发时的回调函数。
   *
   * @defaultValue undefined
   */
  onOpen?: (event: Event, ws: WebSocket) => void
  /**
   * 当 WebSocket 的 close 事件被触发时的回调函数。
   *
   * @defaultValue undefined
   */
  onClose?: (event: CloseEvent, ws: WebSocket) => void
  /**
   * 当 WebSocket 的 error 事件被触发时的回调函数。
   *
   * @defaultValue undefined
   */
  onError?: (event: Event, ws: WebSocket) => void
  /**
   * 当 WebSocket 的 message 事件被触发时的回调函数。
   *
   * @defaultValue undefined
   */
  onMessage?: (event: MessageEvent, ws: WebSocket) => void
  /**
   * 当 WebSocket 连接打开失败时的回调函数,比如错误、无效的 URL,会导致 ws 在创建连接时失败,并关闭连接。
   *
   * @defaultValue undefined
   */
  onOpenFailed?: (event: CloseEvent, ws: WebSocket) => void
  /**
   * 心跳配置,设置为 true 时使用默认配置,参考 UseWebSocketOptionsHeartbeat 的默认配置。
   *
   * @defaultValue false
   */
  heartbeat?: boolean | UseWebSocketOptionsHeartbeat
  /**
   * 是否在连接断开时自动重连,count 可以为重试次数或者函数,函数返回 true 时继续重连,返回 false 时停止重连。
   *
   * @defaultValue true => { count: () => true, interval: 1_000 }
   */
  reconnect?: boolean | UseWebSocketOptionsReconnect
  /**
   * 是否立即打开 WebSocket 连接,当传入了 WS URL 时,默认为 true,否则为 false。
   */
  immediate?: boolean
  /**
   * 是否在组件卸载时关闭 WebSocket 连接。
   *
   * @defaultValue true
   */
  closeOnUnmount?: boolean
  /**
   * WebSocket 的额外子协议。
   *
   * @defaultValue []
   */
  protocols?: string | string[]
  /**
   * 过滤传递至 `onMessage` 回调的消息,返回 `true` 时忽略该消息。
   *
   * 对于过滤掉心跳消息很有用。
   *
   * @defaultValue undefined
   */
  filter?: (event: MessageEvent, ws: WebSocket) => boolean
}

返回值

export interface UseWebSocketReturns<HasURL extends boolean> {
  /**
   * 创建的 WebSocket 实例.
   */
  ws: WebSocket | null
  /**
   * 发送消息到服务器。
   */
  send: (data: UseWebSocketSendable) => void
  /**
   * WebSocket 的当前状态。
   */
  readyState: UseWebSocketReturnsReadyState
  /**
   * 关闭 WebSocket 连接。
   */
  close: () => Promise<void>
  /**
   * 打开 WebSocket 连接,当存在旧的连接时会先关闭旧连接。
   */
  open: HasURL extends true ? () => Promise<void> : (wsUrl?: string, protocols?: string | string[]) => Promise<void>
}

export type UseWebSocketReturnsReadyState =
  | typeof WebSocket.CONNECTING
  | typeof WebSocket.OPEN
  | typeof WebSocket.CLOSING
  | typeof WebSocket.CLOSED