| import { useState, useEffect, useRef, useCallback } from 'react';
|
|
|
| export const useWebSocket = (url) => {
|
| const [data, setData] = useState(null);
|
| const [connected, setConnected] = useState(false);
|
| const ws = useRef(null);
|
| const reconnectTimer = useRef(null);
|
| const mountedRef = useRef(true);
|
| const reconnectDelay = useRef(1000);
|
|
|
| const connect = useCallback(() => {
|
| if (!mountedRef.current) return;
|
|
|
|
|
| if (ws.current) {
|
| ws.current.onopen = null;
|
| ws.current.onclose = null;
|
| ws.current.onmessage = null;
|
| ws.current.onerror = null;
|
| if (ws.current.readyState === WebSocket.OPEN || ws.current.readyState === WebSocket.CONNECTING) {
|
| ws.current.close();
|
| }
|
| }
|
|
|
| console.log('[WS] Connecting to', url);
|
| ws.current = new WebSocket(url);
|
|
|
| ws.current.onopen = () => {
|
| if (!mountedRef.current) return;
|
| console.log('[WS] Connected');
|
| setConnected(true);
|
| reconnectDelay.current = 1000;
|
| };
|
|
|
| ws.current.onclose = (event) => {
|
| if (!mountedRef.current) return;
|
| console.log('[WS] Disconnected, code:', event.code);
|
| setConnected(false);
|
|
|
|
|
| const delay = reconnectDelay.current;
|
| reconnectDelay.current = Math.min(delay * 2, 10000);
|
| console.log(`[WS] Reconnecting in ${delay}ms...`);
|
| reconnectTimer.current = setTimeout(() => {
|
| if (mountedRef.current) connect();
|
| }, delay);
|
| };
|
|
|
| ws.current.onmessage = (event) => {
|
| try {
|
| const message = JSON.parse(event.data);
|
| setData(message);
|
| } catch (err) {
|
| console.error('[WS] Parse Error', err);
|
| }
|
| };
|
|
|
| ws.current.onerror = (err) => {
|
| console.error('[WS] Error', err);
|
| };
|
| }, [url]);
|
|
|
| useEffect(() => {
|
| mountedRef.current = true;
|
| connect();
|
|
|
| return () => {
|
| mountedRef.current = false;
|
| clearTimeout(reconnectTimer.current);
|
| if (ws.current) {
|
| ws.current.onopen = null;
|
| ws.current.onclose = null;
|
| ws.current.onmessage = null;
|
| ws.current.onerror = null;
|
| ws.current.close();
|
| }
|
| };
|
| }, [connect]);
|
|
|
| const sendMessage = useCallback((msg) => {
|
| if (ws.current && ws.current.readyState === WebSocket.OPEN) {
|
| ws.current.send(JSON.stringify(msg));
|
| }
|
| }, []);
|
|
|
| return { connected, data, sendMessage };
|
| };
|
|
|