guandan.dev

guandan.dev

https://git.tonybtw.com/guandan.dev.git git://git.tonybtw.com/guandan.dev.git
1,226 bytes raw
1
import { useCallback, useEffect, useRef, useState } from 'react'
2
import { Message } from '../game/types'
3
4
type Message_Handler = (msg: Message) => void
5
6
export function use_websocket(url: string) {
7
  const [connected, set_connected] = useState(false)
8
  const ws_ref = useRef<WebSocket | null>(null)
9
  const handlers_ref = useRef<Map<string, Message_Handler>>(new Map())
10
11
  useEffect(() => {
12
    const ws = new WebSocket(url)
13
    ws_ref.current = ws
14
15
    ws.onopen = () => {
16
      set_connected(true)
17
    }
18
19
    ws.onclose = () => {
20
      set_connected(false)
21
    }
22
23
    ws.onmessage = (event) => {
24
      const msg: Message = JSON.parse(event.data)
25
      const handler = handlers_ref.current.get(msg.type)
26
      if (handler) {
27
        handler(msg)
28
      }
29
    }
30
31
    return () => {
32
      ws.close()
33
    }
34
  }, [url])
35
36
  const send = useCallback((msg: Message) => {
37
    if (ws_ref.current && ws_ref.current.readyState === WebSocket.OPEN) {
38
      ws_ref.current.send(JSON.stringify(msg))
39
    }
40
  }, [])
41
42
  const on = useCallback((type: string, handler: Message_Handler) => {
43
    handlers_ref.current.set(type, handler)
44
    return () => {
45
      handlers_ref.current.delete(type)
46
    }
47
  }, [])
48
49
  return { connected, send, on }
50
}