← back to Dw Boardroom V2
frontend/src/hooks/useWebSocket.ts
55 lines
import { useState, useEffect, useRef, useCallback } from 'react';
import type { WSEvent } from '../types';
const WS_URL = `ws://${window.location.host}/ws`;
const MAX_EVENTS = 200;
export function useWebSocket() {
const [events, setEvents] = useState<WSEvent[]>([]);
const [connected, setConnected] = useState(false);
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimer = useRef<number>();
const connect = useCallback(() => {
if (wsRef.current?.readyState === WebSocket.OPEN) return;
try {
const ws = new WebSocket(WS_URL);
wsRef.current = ws;
ws.onopen = () => {
setConnected(true);
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
};
ws.onmessage = (evt) => {
try {
const event: WSEvent = JSON.parse(evt.data);
setEvents(prev => [...prev.slice(-MAX_EVENTS), event]);
} catch {}
};
ws.onclose = () => {
setConnected(false);
reconnectTimer.current = window.setTimeout(connect, 3000);
};
ws.onerror = () => {
ws.close();
};
} catch {}
}, []);
useEffect(() => {
connect();
return () => {
if (wsRef.current) wsRef.current.close();
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
};
}, [connect]);
const clearEvents = useCallback(() => setEvents([]), []);
return { events, connected, clearEvents };
}