Skip to content

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

@E2-Meghanadhan

Description

@E2-Meghanadhan

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..

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions