Skip to content

Abhishek-Chougule/react-socket-listener

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“‘ react-socket-listener

A generic React hook for real-time event listening with any socket implementation (Socket.IO, WebSocket, etc.).
No more vendor lock-in! Works with Frappe/ERPNext, custom backends, or any real-time system.


πŸš€ Features

✨ Generic & Flexible

  • πŸ”Œ Works with any socket implementation (Socket.IO, WebSocket, custom)
  • 🎯 Zero dependencies - no vendor lock-in
  • πŸ”„ Backward compatible with existing Frappe/ERPNext projects

πŸ›  Advanced Features

  • πŸ”„ Auto-reconnection with exponential backoff
  • πŸ“Š Connection statistics and monitoring
  • πŸŽ›οΈ Event filtering and custom subscriptions
  • πŸ” Retry logic for failed operations
  • πŸ› Debug mode for development
  • πŸ“ˆ Performance monitoring

🎯 Easy Integration

  • ⚑ Simple React Hook API
  • πŸ“¦ Ready-to-use NPM package
  • πŸ”§ Built-in adapters for popular socket libraries
  • πŸ“š Comprehensive TypeScript support

πŸ“¦ Installation

Easy Installation (Recommended)

npm install react-socket-listener
# or
yarn add react-socket-listener

If you encounter dependency conflicts:

npm install react-socket-listener --legacy-peer-deps
# or
yarn add react-socket-listener --legacy-peer-deps

Optional Dependencies

For Socket.IO support:

npm install socket.io-client

For Frappe/ERPNext support:

npm install frappe-react-sdk

Troubleshooting Installation Issues

If you're getting React version conflicts:

  1. Clear npm cache:

    npm cache clean --force
  2. Use legacy peer deps:

    npm install react-socket-listener --legacy-peer-deps
  3. Force installation (if needed):

    npm install react-socket-listener --force
  4. Check your React version:

    npm list react

    This package supports React 17, 18, and 19.


πŸ›  Usage

πŸ†• New Generic API (Recommended)

With Frappe Socket.IO

import React from "react";
import { useGenericEventListener, createSocketIOAdapter } from "react-socket-listener";
import { FrappeContext, FrappeConfig } from 'frappe-react-sdk';
import { useContext  } from "react";


function CustomerList() {
  // Create socket adapter
  const {socket} = useContext(FrappeContext) as FrappeConfig;
  
  const {
    viewers,
    socketStatus,
    isConnected,
    emitEvent,
    getStats
  } = useGenericEventListener(
    socket,
    { doctype: "Customer" },
    { 
      debug: true,
      autoReconnect: true,
      maxReconnectAttempts: 5
    },
    (event) => {
      console.log("πŸ“© Incoming event:", event);
    }
  );

  return (
    <div>
      <h2>Customer Monitor</h2>
      <p>πŸ”Œ Status: {socketStatus} {isConnected ? "🟒" : "πŸ”΄"}</p>
      <p>πŸ‘₯ Viewers: {viewers.join(", ") || "None"}</p>
      <p>πŸ“Š Stats: {JSON.stringify(getStats())}</p>

      <button onClick={() => emitEvent("custom_event", { message: "Hello!" })}>
        πŸ”” Emit Event
      </button>
    </div>
  );
}

With Socket.IO

import React from "react";
import { useGenericEventListener, createSocketIOAdapter } from "react-socket-listener";

function CustomerList() {
  // Create socket adapter
  const socket = createSocketIOAdapter("http://localhost:8000");
  
  const {
    viewers,
    socketStatus,
    isConnected,
    emitEvent,
    getStats
  } = useGenericEventListener(
    socket,
    { doctype: "Customer" },
    { 
      debug: true,
      autoReconnect: true,
      maxReconnectAttempts: 5
    },
    (event) => {
      console.log("πŸ“© Incoming event:", event);
    }
  );

  return (
    <div>
      <h2>Customer Monitor</h2>
      <p>πŸ”Œ Status: {socketStatus} {isConnected ? "🟒" : "πŸ”΄"}</p>
      <p>πŸ‘₯ Viewers: {viewers.join(", ") || "None"}</p>
      <p>πŸ“Š Stats: {JSON.stringify(getStats())}</p>

      <button onClick={() => emitEvent("custom_event", { message: "Hello!" })}>
        πŸ”” Emit Event
      </button>
    </div>
  );
}

With Native WebSocket

import React from "react";
import { useGenericEventListener, createWebSocketAdapter } from "react-socket-listener";

function RealTimeApp() {
  const socket = createWebSocketAdapter("ws://localhost:8080");
  
  const { socketStatus, emitEvent } = useGenericEventListener(
    socket,
    { doctype: "Orders", customEvents: ["order_updated", "payment_received"] },
    { debug: true }
  );

  return (
    <div>
      <p>Status: {socketStatus}</p>
      <button onClick={() => emitEvent("ping", { timestamp: Date.now() })}>
        Ping Server
      </button>
    </div>
  );
}

With Custom Socket Implementation

import React from "react";
import { useGenericEventListener, GenericSocket } from "react-socket-listener";

// Your custom socket implementation
class MyCustomSocket implements GenericSocket {
  connected = false;
  // ... implement all required methods
}

function CustomApp() {
  const socket = new MyCustomSocket();
  
  const { socketStatus, emitEvent } = useGenericEventListener(
    socket,
    { doctype: "Products" }
  );

  return <div>Status: {socketStatus}</div>;
}

πŸ”„ Legacy API (Backward Compatible)

import React from "react";
import { useFrappeEventListener } from "react-socket-listener";

function CustomerList() {
  const { viewers, socketStatus, emitEvent } = useFrappeEventListener(
    "Customer",
    (event) => {
      console.log("πŸ“© Incoming event:", event);
    }
  );

  return (
    <div>
      <h2>Customer Monitor</h2>
      <p>πŸ”Œ Socket status: {socketStatus}</p>
      <p>πŸ‘₯ Viewers: {viewers.join(", ") || "None"}</p>
    </div>
  );
}

Comparison

Feature Current frappeEventListener.tsx react-socket-listener
Socket Support Frappe-specific only βœ… Generic (Socket.IO, WebSocket, custom)
Auto-reconnection ❌ Basic βœ… Advanced with exponential backoff
Connection Monitoring ❌ Basic status βœ… Comprehensive stats & monitoring
Event Filtering ❌ None βœ… Advanced filtering options
Debug Mode ❌ Commented out βœ… Built-in debug logging
Retry Logic ❌ None βœ… Configurable retry mechanism
TypeScript Support ❌ Basic βœ… Full TypeScript definitions
Performance Monitoring ❌ None βœ… Built-in performance stats
Vendor Lock-in ❌ Frappe-only βœ… Zero dependencies, vendor-agnostic

πŸ“š API Reference

useGenericEventListener(socket, initialSubscription?, config?, onEventCallback?)

Parameter Type Required Description
socket GenericSocket | null βœ… Socket instance (use adapters or implement GenericSocket)
initialSubscription SubscriptionOptions ❌ Initial subscription configuration
config EventListenerConfig ❌ Event listener configuration
onEventCallback function ❌ Callback for incoming events

Returns

{
  viewers: string[];                                    // Active viewers
  socketStatus: SocketStatus;                          // Connection status
  isConnected: boolean;                                // Connection state
  emitEvent: (event: string, data?: any) => Promise<boolean>;  // Emit events
  subscribe: (options: SubscriptionOptions) => void;   // Subscribe to events
  unsubscribe: (doctype: string) => void;              // Unsubscribe
  getStats: () => ConnectionStats;                     // Get statistics
  reconnect: () => void;                               // Manual reconnect
  clearListeners: () => void;                          // Clear all listeners
}

Configuration Options

interface EventListenerConfig {
  autoReconnect?: boolean;           // Auto-reconnect on disconnect
  maxReconnectAttempts?: number;     // Max reconnection attempts
  reconnectDelay?: number;           // Delay between reconnects (ms)
  debug?: boolean;                   // Enable debug logging
  eventFilters?: {                   // Event filtering
    eventTypes?: string[];
    doctypes?: string[];
  };
  retryConfig?: {                    // Retry configuration
    maxAttempts?: number;
    delay?: number;
  };
}

πŸ”§ Adapters

Socket.IO Adapter

import { createSocketIOAdapter, createFrappeSocketAdapter } from "react-socket-listener";

// Basic Socket.IO
const socket = createSocketIOAdapter("http://localhost:8000");

// Frappe-compatible Socket.IO
const frappeSocket = createFrappeSocketAdapter("http://localhost:8000", {
  token: "your-auth-token",
  userId: "user@example.com"
});

WebSocket Adapter

import { createWebSocketAdapter } from "react-socket-listener";

const socket = createWebSocketAdapter("ws://localhost:8080");

🎯 Use Cases

  • Frappe/ERPNext real-time updates
  • Custom backend real-time features
  • Multi-tenant applications
  • IoT device monitoring
  • Chat applications
  • Live dashboards
  • Collaborative editing

πŸ“„ Requirements

  • React β‰₯ 17
  • TypeScript (optional but recommended)

πŸ› Common Issues & Solutions

Issue: "socket.io-client not found"

Solution: Install the optional dependency:

npm install socket.io-client

Issue: "frappe-react-sdk not found"

Solution: Install the optional dependency:

npm install frappe-react-sdk

Issue: React version conflicts

Solution: Use legacy peer deps:

npm install react-socket-listener --legacy-peer-deps

Issue: TypeScript errors

Solution: Make sure you have TypeScript installed:

npm install -D typescript @types/react

Issue: Socket connection fails

Solution: Check your server URL and ensure the server is running:

// Debug connection
const { debugInfo, connectionError } = useSocketConnection();
console.log('Debug info:', debugInfo);
console.log('Connection error:', connectionError);

🀝 Contributing

PRs and issues are welcome!
Please open an issue first to discuss what you'd like to change.


πŸ›‘ License

MIT Β© 2025 Abhishek-Chougule

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published