"use client" import { useEffect, useRef, useState } from "react" export default function WsDemo() { const [connected, setConnected] = useState(false) const [messages, setMessages] = useState([]) const [input, setInput] = useState("") const wsRef = useRef(null) useEffect(() => { const protocol = window.location.protocol === "https:" ? "wss" : "ws" const url = `${protocol}://${window.location.host}/api/ws` const existing = (window as any).__ws as WebSocket | undefined const ws = existing && (existing.readyState === WebSocket.OPEN || existing.readyState === WebSocket.CONNECTING) ? existing : new WebSocket(url) ;(window as any).__ws = ws wsRef.current = ws const onOpen = (event: Event) => { console.log("onOpen", event) setConnected(true) } const onClose = (event: Event) => { console.log("onClose", event) setConnected(false) } const onError = (event: Event) => { console.log("onError", event) setConnected(false) } const onMessage = (event: MessageEvent) => { console.log("onMessage", event) try { const payload = JSON.parse(event.data) if (payload?.type === "server:hello" || payload?.type === "server:pong") { setMessages((prev) => [...prev, payload.message]) } } catch {} } ws.addEventListener("open", onOpen) ws.addEventListener("close", onClose) ws.addEventListener("error", onError) ws.addEventListener("message", onMessage) const beforeUnload = () => { try { ws.close() } catch {} } window.addEventListener("beforeunload", beforeUnload) return () => { console.log("unmounting") ws.removeEventListener("open", onOpen) ws.removeEventListener("close", onClose) ws.removeEventListener("error", onError) ws.removeEventListener("message", onMessage) window.removeEventListener("beforeunload", beforeUnload) } }, []) const sendPing = () => { const msg = input || "ping" wsRef.current?.send(JSON.stringify({ type: "client:ping", message: msg })) setInput("") } return (
WebSocket {connected ? "connected" : "disconnected"}
setInput(e.target.value)} placeholder="Type a message" />
    {messages.map((m, i) => (
  • {m}
  • ))}
) }