Add frontend/src/hooks/useWebSocket.ts

This commit is contained in:
Zac Gaetano 2026-04-14 09:21:17 -04:00
parent a9472e4715
commit 8691ccd060

View file

@ -0,0 +1,67 @@
import { useEffect, useRef, useState, useCallback } from 'react';
import { WebSocketMessage } from '../types';
export function useWebSocket(url: string) {
const [isConnected, setIsConnected] = useState(false);
const [lastMessage, setLastMessage] = useState<WebSocketMessage | null>(null);
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
const connect = useCallback(() => {
try {
const ws = new WebSocket(url);
ws.onopen = () => {
console.log('WebSocket connected');
setIsConnected(true);
};
ws.onmessage = (event) => {
try {
const message: WebSocketMessage = JSON.parse(event.data);
setLastMessage(message);
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
setIsConnected(false);
};
ws.onclose = () => {
console.log('WebSocket disconnected');
setIsConnected(false);
// Schedule reconnect after 3000ms
reconnectTimer.current = setTimeout(() => {
console.log('Attempting to reconnect...');
connect();
}, 3000);
};
wsRef.current = ws;
} catch (error) {
console.error('Failed to create WebSocket:', error);
setIsConnected(false);
}
}, [url]);
useEffect(() => {
connect();
return () => {
// Cleanup: close ws and clear reconnect timer
if (wsRef.current) {
wsRef.current.close();
wsRef.current = null;
}
if (reconnectTimer.current) {
clearTimeout(reconnectTimer.current);
reconnectTimer.current = null;
}
};
}, [connect]);
return { isConnected, lastMessage };
}