Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

share : true is not working as expected. Duplicate websockets of same url are generated. #262

Open
E2-Meghanadhan opened this issue Feb 25, 2025 · 0 comments

Comments

@E2-Meghanadhan
Copy link

E2-Meghanadhan commented Feb 25, 2025

The Utility I have written to Reuse:

//2 websocketConfig.js
import { useEffect, useRef } from 'react';
import useWebSocket from 'react-use-websocket';
import getWebsocketHost from '../getWebsockerHost';

// IMPORTANT: Get the URL once and store it
const SOCKET_URL = 'ws://10.10.1.151/webSocketService';

// Create a singleton WebSocket instance
let websocketInstance = null;
let subscribers = new Set();

export function useSharedWebSocket() {
  // Use a consistent reference for options object
  const optionsRef = useRef({
    share: true,
    retryOnError: true,
    shouldReconnect: () => true,
    reconnectAttempts: 10,
    reconnectInterval: 3000,
    onOpen: (e) => console.log('Socket opened', e),
    onClose: (e) => console.log('Socket closed', e),
    onError: (e) => console.log('Socket error', e),
  });

  // Use the hook with persistent references
  const { sendMessage, lastMessage, readyState, getWebSocket } = useWebSocket(
    SOCKET_URL, 
    optionsRef.current
  );

  // Store the instance if it doesn't exist
  useEffect(() => {
    if (!websocketInstance && readyState === 1) {
      websocketInstance = getWebSocket();
      console.log('WebSocket instance created and stored');
    }
    
    // Add to subscribers
    const id = Date.now().toString();
    subscribers.add(id);
    console.log(`Subscriber added: ${id}, total: ${subscribers.size}`);
    
    return () => {
      // Remove from subscribers on cleanup
      subscribers.delete(id);
      console.log(`Subscriber removed: ${id}, total: ${subscribers.size}`);
    };
  }, [readyState, getWebSocket]);

  return { sendMessage, lastMessage, readyState };
}

The above code using as utitlity in all components in order to maintain single websocket connection throughout the application and reconnecting automatically..

Using in Components:

import useWebSocket, { ReadyState } from 'react-use-websocket';
const getWebsocketHost = () => {
    // Replace with your actual WebSocket URL logic
    return 'wss://your-websocket-server.com';
  };
  
  // Generate a random client ID
  const clientId = React.useMemo(() => {
    return Math.floor(Math.random() * Math.pow(16, 6*2)).toString(16).padStart(6,'0');
  }, []);

  // Configure WebSocket options
  const {
    sendMessage,
    lastMessage,
    readyState,
    getWebSocket
  } = useWebSocket(getWebsocketHost(), {
    // Will attempt to reconnect on all close events
    shouldReconnect: (closeEvent) => true,
    // Reconnect interval in ms
    reconnectInterval: 30000,
    // Optional: maximum number of reconnect attempts
    reconnectAttempts: 10,
    // Optional: custom onOpen handler
    onOpen: () => {
      console.log('WebSocket Client Connected Dashboard');
      sendPingMessage('open');
      
      // Setup ping interval
      const pingIntervalId = setInterval(() => {
        console.log('Socket ping interval will be attempted in 2 minutes once.');
        sendPingMessage('ping');
      }, 120 * 1000);
      
      // Clear interval on component unmount
      return () => clearInterval(pingIntervalId);
    },
    // Optional: custom onClose handler
    onClose: (event) => {
      console.log("Entering onclose Dash");
      console.log('Socket is closed. Reconnect will be attempted automatically.', event.reason);
    },
    // Optional: custom onError handler
    onError: (event) => {
      console.error('Socket encountered error: ', event.message);
    }
  });

const sendPingMessage = useCallback((type) => {
    sendMessage(JSON.stringify({
      type: type,
      client_id: clientId,
      user_id: sessionStorage.getItem("user_id"),
      user_type_id: sessionStorage.getItem("user_type_id")
    }));
  }, [sendMessage, clientId]);

useEffect(() => {
    if (lastMessage !== null) {
      try {
        const webSocketResponse = JSON.parse(lastMessage.data);
        
        messages ..... here
        }
      } catch (error) {
        console.error("Error parsing WebSocket message:", error);
      }
    }
  }, [lastMessage]);

The PROBLEM :

  1. For every new component mounting a new websocket connection is initiating not even closing the last one.. I have used share: true also..
  2. During reconnection, the old connected connection is still alive.. Finally after reconnection we need to have only one live connection right? But i am having two...with 101..
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant