Team Ai
Apppublic

IDKHowToCodeFr/tinyml-backend

sourceHugging Faceupdated 2d agoView on Hugging Face
1likes
useResilientSocket.ts60 linesDownload Raw Back to hooks
1import { useEffect, useRef, useState } from "react";2 3export type ConnectionStatus = 'connected' | 'reconnecting' | 'disconnected';4 5export function useResilientSocket(url: string, onMessage: (msg: any) => void) {6  const [status, setStatus] = useState<ConnectionStatus>('disconnected');7  const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);8  const reconnectAttemptRef = useRef(0);9  const savedCallback = useRef(onMessage);10 11  useEffect(() => {12    savedCallback.current = onMessage;13  }, [onMessage]);14 15  useEffect(() => {16    let ws: WebSocket;17    let isComponentMounted = true;18 19    const connect = () => {20      ws = new WebSocket(url);21      22      ws.onopen = () => {23        if (!isComponentMounted) return;24        setStatus('connected');25        reconnectAttemptRef.current = 0; // Reset attempts26      };27 28      ws.onmessage = (event) => {29        if (!isComponentMounted) return;30        const msg = JSON.parse(event.data);31        savedCallback.current(msg);32      };33 34      ws.onclose = () => {35        if (!isComponentMounted) return;36        setStatus('reconnecting');37        const timeout = Math.min(1000 * (2 ** reconnectAttemptRef.current), 30000); // Max 30s38        reconnectAttemptRef.current += 1;39        40        reconnectTimeoutRef.current = setTimeout(connect, timeout);41      };42 43      ws.onerror = () => {44        if (!isComponentMounted) return;45        ws.close(); // Force trigger onclose46      };47    };48 49    connect();50 51    return () => {52      isComponentMounted = false;53      if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current);54      if (ws) ws.close();55    };56  }, [url]);57 58  return status;59}60