import { useState, useEffect, useCallback, useRef } from 'react';
interface WebSocketMessage {
event: string;
data: any;
timestamp: string;
}
interface UseWebSocketReturn {
connected: boolean;
lastMessage: WebSocketMessage | null;
send: (data: any) => void;
}
export function useWebSocket(): UseWebSocketReturn {
const [connected, setConnected] = useState(false);
const [lastMessage, setLastMessage] = useState<WebSocketMessage | null>(null);
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const connect = useCallback(() => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/ws`;
const ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('WebSocket connected');
setConnected(true);
};
ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data) as WebSocketMessage;
setLastMessage(message);
console.log('WebSocket message:', message);
} catch (e) {
console.error('Failed to parse WebSocket message:', e);
}
};
ws.onclose = () => {
console.log('WebSocket disconnected');
setConnected(false);
wsRef.current = null;
// 尝试重连
reconnectTimeoutRef.current = setTimeout(() => {
console.log('Attempting to reconnect...');
connect();
}, 3000);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
wsRef.current = ws;
}, []);
useEffect(() => {
connect();
return () => {
if (reconnectTimeoutRef.current) {
clearTimeout(reconnectTimeoutRef.current);
}
if (wsRef.current) {
wsRef.current.close();
}
};
}, [connect]);
const send = useCallback((data: any) => {
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
wsRef.current.send(JSON.stringify(data));
}
}, []);
return { connected, lastMessage, send };
}