8
Hooks

useWebSocket

A hook for managing WebSocket connections with reconnection logic and message handling.

useWebSocket

The useWebSocket hook provides a robust way to manage WebSocket connections in React applications. It handles connection management, automatic reconnection, message parsing, and more with support for both text and binary data formats.

WebSocket Demo
CLOSED
wss://echo.example.com

Connect to start messaging

This is a simulated WebSocket connection for demonstration purposes.

Installation

Install the useWebSocket hook using:

npx axionjs-ui add hook use-web-socket

File Structure

use-web-socket.ts

Parameters

PropTypeDefault
options
WebSocketOptions
Required

Return Value

PropTypeDefault
readyState
number
-
isConnecting
boolean
-
isOpen
boolean
-
isClosing
boolean
-
isClosed
boolean
-
lastMessage
WebSocketMessage | null
-
messages
WebSocketMessage[]
-
error
Event | null
-
connect
() => void
-
disconnect
() => void
-
send
(data: string | ArrayBufferLike | Blob | ArrayBufferView) => void
-
socket
WebSocket | null
-
READY_STATE
{ CONNECTING: 0; OPEN: 1; CLOSING: 2; CLOSED: 3 }
-

Examples

Chat Application

A simple chat application using WebSockets for real-time communication.

WebSocket Chat Application
Disconnected

Contacts

J

John Doe

3 messages

J

Jane Smith

0 messages

A

Alice Johnson

3 messages

Select a contact to start chatting

Select a contact to start chatting

This is a simulated chat application using WebSockets for real-time communication.

Real-time Data Dashboard

import { useState, useEffect } from "react";
import { useWebSocket } from "@/hooks/use-web-socket";
 
interface Metric {
  name: string;
  value: number;
  timestamp: number;
}
 
function RealTimeMetricsDashboard() {
  const [metrics, setMetrics] = useState<Record<string, Metric>>({});
  const [isConnected, setIsConnected] = useState(false);
  
  const { 
    isOpen, 
    lastMessage, 
    connect, 
    disconnect 
  } = useWebSocket({
    url: 'wss://metrics.example.com/socket',
    jsonMode: true,
    onOpen: () => {
      setIsConnected(true);
      console.log('Dashboard connected to metrics server');
    },
    onClose: () => {
      setIsConnected(false);
      console.log('Dashboard disconnected from metrics server');
    },
  });
  
  // Process incoming metric updates
  useEffect(() => {
    if (lastMessage?.data) {
      const metric = lastMessage.data as Metric;
      setMetrics(prev => ({
        ...prev,
        [metric.name]: metric,
      }));
    }
  }, [lastMessage]);
  
  return (
    <div>
      <div>
        <h1>Real-time Metrics Dashboard</h1>
        <button onClick={isConnected ? disconnect : connect}>
          {isConnected ? 'Disconnect' : 'Connect'}
        </button>
        <span>Status: {isConnected ? 'Connected' : 'Disconnected'}</span>
      </div>
      
      <div>
        {Object.values(metrics).length === 0 ? (
          <p>No metrics available yet. Connect to start receiving data.</p>
        ) : (
          <div>
            {Object.values(metrics).map(metric => (
              <div key={metric.name}>
                <h3>{metric.name}</h3>
                <div>{metric.value}</div>
                <div>
                  Updated: {new Date(metric.timestamp).toLocaleTimeString()}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

Binary Data Handling

import { useWebSocket } from "@/hooks/use-web-socket";
 
function BinaryDataExample() {
  const { isOpen, lastMessage, send } = useWebSocket({
    url: 'wss://binary.example.com/socket',
    binaryType: 'arraybuffer', // Receive binary data as ArrayBuffer
    autoConnect: true,
  });
  
  // Send a binary message
  const sendBinaryMessage = () => {
    if (!isOpen) return;
    
    // Create a simple binary message (Uint8Array)
    const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
    send(binaryData);
  };
  
  // Process received binary data
  const processLastMessage = () => {
    if (!lastMessage || !(lastMessage.data instanceof ArrayBuffer)) {
      return 'No binary message received';
    }
    
    // Convert ArrayBuffer to readable format
    const dataView = new DataView(lastMessage.data);
    const result = [];
    
    for (let i = 0; i < dataView.byteLength; i++) {
      result.push(dataView.getUint8(i));
    }
    
    return 'Received binary data: ' + result.join(', ');
  };
  
  return (
    <div>
      <h2>Binary Data WebSocket Example</h2>
      <div>
        <button onClick={sendBinaryMessage} disabled={!isOpen}>
          Send Binary Message
        </button>
      </div>
      <div>
        <h3>Last Message:</h3>
        <pre>{processLastMessage()}</pre>
      </div>
    </div>
  );
}

Advanced Usage

Custom Reconnection Strategy

Implementing a custom reconnection strategy with increasing delays and a cap on retry attempts:

import { useWebSocket } from "@/hooks/use-web-socket";
 
function CustomReconnectExample() {
  // Track retry count in user interface
  const [uiRetryCount, setUiRetryCount] = useState(0);
  
  const {
    isOpen,
    connect,
    disconnect,
    readyState,
  } = useWebSocket({
    url: 'wss://example.com/socket',
    autoReconnect: true,
    reconnectInterval: 1000, // Start with 1 second
    maxReconnectInterval: 60000, // Cap at 1 minute
    maxReconnectAttempt: 10, // Only try 10 times
    exponentialBackoff: true, // Use exponential backoff
    onClose: () => {
      setUiRetryCount(prev => prev + 1);
    },
  });
  
  // Calculate and display next reconnect time
  const getNextRetryTime = () => {
    if (readyState !== 3 || uiRetryCount >= 10) return null;
    
    // Calculate exponential backoff: min(reconnectInterval * 2 ^ retryCount, maxReconnectInterval)
    const nextDelay = Math.min(1000 * Math.pow(2, uiRetryCount), 60000);
    return `${(nextDelay / 1000).toFixed(1)} seconds`;
  };
  
  return (
    <div>
      <h2>Custom Reconnection Strategy</h2>
      <div>
        <p>Connection Status: {
          readyState === 0 ? 'Connecting' :
          readyState === 1 ? 'Connected' :
          readyState === 2 ? 'Closing' : 'Disconnected'
        }</p>
        <p>Retry Attempts: {uiRetryCount} / 10</p>
        {getNextRetryTime() && <p>Next retry in: {getNextRetryTime()}</p>}
      </div>
      <div>
        <button onClick={connect} disabled={isOpen}>Connect</button>
        <button onClick={disconnect} disabled={!isOpen}>Disconnect</button>
        <button onClick={() => setUiRetryCount(0)}>Reset Counter</button>
      </div>
    </div>
  );
}

Use Cases

  • Chat Applications: Real-time messaging and presence updates
  • Live Dashboards: Displaying real-time metrics and analytics
  • Collaborative Editing: Real-time document editing
  • Gaming: Multiplayer game state synchronization
  • Financial Applications: Real-time market data and trading
  • IoT Dashboards: Real-time device monitoring and control
  • Notifications: Instant alerts and notifications
  • Live Comments: Real-time comment sections and reactions

Browser Support and Limitations

WebSockets are supported in all modern browsers, but there are some considerations:

  • WebSockets require a specific server implementation
  • Some firewalls may block WebSocket connections
  • Proxy servers may not properly handle WebSocket connections
  • Maximum message size limitations vary by browser and server
  • Some networks may terminate idle connections

Performance Considerations

  • Message Frequency: High message rates can impact performance
  • Keep Alive: Consider implementing heartbeat messages for long-lived connections
  • Message Size: Keep message payloads small for better performance
  • JSON Parsing: Be cautious with large data structures and deep nesting
  • Binary Data: Use binary formats for large datasets when appropriate

Security Considerations

  • Always use secure WebSocket connections (wss:// protocol)
  • Validate all incoming messages before processing
  • Implement proper authentication and authorization
  • Be careful with sensitive data transmission
  • Protect against cross-site WebSocket hijacking (CSWSH)

Best Practices

  • Always check connection status before sending messages
  • Implement proper error handling and reconnection logic
  • Use appropriate status indicators in the UI
  • Consider fallback mechanisms when WebSockets aren’t available
  • Add a clean disconnect when components unmount
  • Use debouncing for high-frequency operations
  • Implement proper error handling for message parsing

On this page