use-realtime 1.0.0 โ 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -146
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,222 +1,282 @@
|
|
|
1
|
-
|
|
2
|
-
<div align="center">
|
|
1
|
+
markdown
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
https://img.shields.io/npm/l/use-realtime
|
|
6
|
-
https://img.shields.io/badge/TypeScript-Ready-blue
|
|
3
|
+
# use-realtime ๐
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/use-realtime)
|
|
6
|
+
[](https://www.npmjs.com/package/use-realtime)
|
|
7
|
+
[](https://github.com/yaredabebe/use-realtime/blob/main/LICENSE)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
**Stop rewriting WebSocket boilerplate in every React project.** A production-ready React hook for building real-time features with auto-reconnect, message queuing, and event subscriptions.
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
---
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
## โจ Features
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
- **๐ Auto-reconnect** - Automatically reconnects with configurable retry limits
|
|
17
|
+
- **๐ฆ Message queue** - Never lose messages when offline (queues messages automatically)
|
|
18
|
+
- **๐ก Event-based API** - Simple subscribe/unsubscribe pattern for events
|
|
19
|
+
- **๐ Heartbeat support** - Optional ping-pong to keep connections alive
|
|
20
|
+
- **๐งน Automatic cleanup** - Proper cleanup on component unmount
|
|
21
|
+
- **๐ง TypeScript first** - Full type safety and IntelliSense support
|
|
22
|
+
- **โก Zero dependencies** - Lightweight and tree-shakable
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
---
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
## ๐ฆ Installation
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
๐ Features
|
|
28
|
+
```bash
|
|
29
|
+
npm install use-realtime
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
๐ฆ Message queue (no lost messages)
|
|
32
|
-
๐ก Event-based subscribe/unsubscribe API
|
|
33
|
-
๐ Optional heartbeat (keep connection alive)
|
|
34
|
-
๐งน Automatic cleanup on unmount
|
|
35
|
-
๐ง React-safe & TypeScript-first
|
|
36
|
-
๐ Works with any WebSocket backend
|
|
31
|
+
or
|
|
32
|
+
bash
|
|
37
33
|
|
|
34
|
+
yarn add use-realtime
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
or
|
|
37
|
+
bash
|
|
40
38
|
|
|
41
|
-
npm install use-realtime
|
|
42
|
-
# or
|
|
43
|
-
yarn add use-realtime
|
|
44
|
-
# or
|
|
45
39
|
pnpm add use-realtime
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
๐ Quick Start
|
|
42
|
+
jsx
|
|
43
|
+
|
|
44
|
+
import React, { useEffect } from 'react';
|
|
48
45
|
import { useRealtime } from 'use-realtime';
|
|
49
46
|
|
|
50
|
-
function
|
|
47
|
+
function ChatComponent() {
|
|
51
48
|
const { emit, subscribe, isConnected } = useRealtime({
|
|
52
|
-
url: 'wss://
|
|
49
|
+
url: 'wss://your-server.com/ws',
|
|
53
50
|
autoReconnect: true,
|
|
54
51
|
});
|
|
55
52
|
|
|
56
|
-
// Subscribe to events
|
|
57
53
|
useEffect(() => {
|
|
58
|
-
const unsubscribe = subscribe('
|
|
59
|
-
console.log('New message:',
|
|
54
|
+
const unsubscribe = subscribe('message', (data) => {
|
|
55
|
+
console.log('New message:', data);
|
|
60
56
|
});
|
|
61
|
-
|
|
57
|
+
|
|
58
|
+
return unsubscribe; // Cleanup on unmount
|
|
62
59
|
}, [subscribe]);
|
|
63
60
|
|
|
61
|
+
const sendMessage = () => {
|
|
62
|
+
emit('chat', { text: 'Hello World!', user: 'You' });
|
|
63
|
+
};
|
|
64
|
+
|
|
64
65
|
return (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
<div>
|
|
67
|
+
<p>Status: {isConnected ? 'โ
Connected' : 'โ Disconnected'}</p>
|
|
68
|
+
<button onClick={sendMessage} disabled={!isConnected}>
|
|
69
|
+
Send Message
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
68
72
|
);
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const realtime = useRealtime({
|
|
75
|
-
url: string, // WebSocket server URL (required)
|
|
76
|
-
autoConnect?: boolean, // Auto connect on mount (default: true)
|
|
77
|
-
autoReconnect?: boolean, // Auto reconnect on disconnect (default: true)
|
|
78
|
-
reconnectAttempts?: number, // Max reconnect attempts (default: 10)
|
|
79
|
-
reconnectInterval?: number, // Reconnect delay in ms (default: 3000)
|
|
80
|
-
heartbeat?: { // Heartbeat configuration
|
|
81
|
-
enabled?: boolean, // Enable heartbeat (default: false)
|
|
82
|
-
interval?: number, // Heartbeat interval in ms (default: 30000)
|
|
83
|
-
message?: any, // Heartbeat message (default: 'ping')
|
|
84
|
-
},
|
|
85
|
-
messageQueue?: { // Offline message queue
|
|
86
|
-
enabled?: boolean, // Enable message queue (default: true)
|
|
87
|
-
maxSize?: number, // Max queue size (default: 100)
|
|
88
|
-
},
|
|
89
|
-
debug?: boolean, // Enable debug logging (default: false)
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
๐ก Sending Messages
|
|
94
|
-
emit(event, data)
|
|
95
|
-
|
|
96
|
-
Send a named event. If the socket is not connected, the message is queued automatically.
|
|
97
|
-
emit('notification', { title: 'New order' });
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
send(data)
|
|
101
|
-
|
|
102
|
-
Send a raw message (no event name).
|
|
103
|
-
|
|
104
|
-
send({ ping: true });
|
|
105
|
-
|
|
75
|
+
๐ Documentation
|
|
76
|
+
Configuration Options
|
|
77
|
+
typescript
|
|
106
78
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
79
|
+
interface RealtimeOptions {
|
|
80
|
+
// Required
|
|
81
|
+
url: string;
|
|
82
|
+
|
|
83
|
+
// Optional (with defaults)
|
|
84
|
+
autoConnect?: boolean; // Default: true
|
|
85
|
+
autoReconnect?: boolean; // Default: true
|
|
86
|
+
reconnectAttempts?: number; // Default: 10
|
|
87
|
+
reconnectInterval?: number; // Default: 3000 (ms)
|
|
88
|
+
|
|
89
|
+
// Heartbeat configuration
|
|
90
|
+
heartbeat?: {
|
|
91
|
+
enabled?: boolean; // Default: false
|
|
92
|
+
interval?: number; // Default: 30000 (ms)
|
|
93
|
+
message?: any; // Default: 'ping'
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Message queue for offline mode
|
|
97
|
+
messageQueue?: {
|
|
98
|
+
enabled?: boolean; // Default: true
|
|
99
|
+
maxSize?: number; // Default: 100
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
debug?: boolean; // Default: false
|
|
103
|
+
}
|
|
110
104
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
Hook Return Values
|
|
106
|
+
Method Description
|
|
107
|
+
subscribe(event, callback) Subscribe to events, returns unsubscribe function
|
|
108
|
+
unsubscribe(event, callback) Unsubscribe from specific event
|
|
109
|
+
emit(event, data) Send event with data
|
|
110
|
+
send(data) Send raw data (auto-wrapped as 'message' event)
|
|
111
|
+
connect() Manually connect
|
|
112
|
+
disconnect() Manually disconnect
|
|
113
|
+
reconnect() Force reconnection
|
|
114
|
+
getQueueSize() Get number of queued messages
|
|
115
|
+
flushQueue() Clear all queued messages
|
|
116
|
+
clearSubscriptions() Remove all event listeners
|
|
117
|
+
State Property Type Description
|
|
118
|
+
isConnected boolean Connection is active
|
|
119
|
+
isConnecting boolean Connection in progress
|
|
120
|
+
isReconnecting boolean Reconnection in progress
|
|
121
|
+
connection ConnectionState Full connection details
|
|
122
|
+
Connection State Object
|
|
123
|
+
typescript
|
|
114
124
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
interface ConnectionState {
|
|
126
|
+
connected: boolean;
|
|
127
|
+
connecting: boolean;
|
|
128
|
+
reconnecting: boolean;
|
|
129
|
+
error: Error | null;
|
|
130
|
+
lastMessageAt: Date | null;
|
|
131
|
+
connectionId: string | null;
|
|
132
|
+
}
|
|
120
133
|
|
|
121
|
-
|
|
134
|
+
๐ก Real-World Examples
|
|
135
|
+
1. Live Chat Application
|
|
122
136
|
jsx
|
|
123
137
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
function ChatRoom() {
|
|
139
|
+
const [messages, setMessages] = useState([]);
|
|
140
|
+
const { subscribe, emit, isConnected } = useRealtime({
|
|
141
|
+
url: 'wss://chat-server.com/ws',
|
|
142
|
+
autoReconnect: true,
|
|
143
|
+
reconnectAttempts: 5,
|
|
144
|
+
});
|
|
130
145
|
|
|
131
|
-
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
const unsubscribe = subscribe('chat-message', (msg) => {
|
|
148
|
+
setMessages(prev => [...prev, msg]);
|
|
149
|
+
});
|
|
150
|
+
return unsubscribe;
|
|
151
|
+
}, [subscribe]);
|
|
132
152
|
|
|
133
|
-
|
|
153
|
+
const sendMessage = (text) => {
|
|
154
|
+
emit('chat-message', { text, timestamp: Date.now() });
|
|
155
|
+
};
|
|
134
156
|
|
|
135
|
-
|
|
157
|
+
// ... render messages and input
|
|
158
|
+
}
|
|
136
159
|
|
|
137
|
-
|
|
160
|
+
2. Live Dashboard
|
|
161
|
+
jsx
|
|
138
162
|
|
|
139
|
-
|
|
163
|
+
function LiveDashboard() {
|
|
164
|
+
const [stats, setStats] = useState({});
|
|
165
|
+
const { subscribe } = useRealtime({
|
|
166
|
+
url: 'wss://api.example.com/live',
|
|
167
|
+
heartbeat: { enabled: true, interval: 15000 },
|
|
168
|
+
});
|
|
140
169
|
|
|
141
|
-
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
const unsubscribe = subscribe('stats-update', (data) => {
|
|
172
|
+
setStats(data);
|
|
173
|
+
});
|
|
174
|
+
return unsubscribe;
|
|
175
|
+
}, [subscribe]);
|
|
142
176
|
|
|
143
|
-
|
|
177
|
+
// ... render dashboard with stats
|
|
178
|
+
}
|
|
144
179
|
|
|
145
|
-
|
|
180
|
+
๐ง Advanced Usage
|
|
181
|
+
Manual Connection Control
|
|
146
182
|
jsx
|
|
147
183
|
|
|
148
|
-
const { connect, disconnect, reconnect } = useRealtime(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
reconnect(); // Force reconnect
|
|
153
|
-
|
|
154
|
-
๐ฆ Message Queue Utilities
|
|
155
|
-
jsx
|
|
184
|
+
const { connect, disconnect, reconnect, isConnected } = useRealtime({
|
|
185
|
+
url: 'wss://example.com',
|
|
186
|
+
autoConnect: false, // Disable auto-connect
|
|
187
|
+
});
|
|
156
188
|
|
|
157
|
-
|
|
189
|
+
// Connect manually
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
connect();
|
|
192
|
+
}, [connect]);
|
|
158
193
|
|
|
159
|
-
|
|
160
|
-
|
|
194
|
+
// Disconnect after 30 seconds
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
if (isConnected) disconnect();
|
|
198
|
+
}, 30000);
|
|
199
|
+
return () => clearTimeout(timer);
|
|
200
|
+
}, [disconnect, isConnected]);
|
|
161
201
|
|
|
162
|
-
|
|
202
|
+
Message Queue (Offline Mode)
|
|
203
|
+
jsx
|
|
163
204
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
205
|
+
const { emit, getQueueSize, flushQueue } = useRealtime({
|
|
206
|
+
url: 'wss://example.com',
|
|
207
|
+
messageQueue: {
|
|
208
|
+
enabled: true,
|
|
209
|
+
maxSize: 50, // Queue up to 50 messages
|
|
210
|
+
},
|
|
211
|
+
});
|
|
168
212
|
|
|
169
|
-
|
|
213
|
+
// Messages are automatically queued when offline
|
|
214
|
+
// and sent when connection is restored
|
|
215
|
+
emit('important-event', { data: 'will not be lost' });
|
|
170
216
|
|
|
171
|
-
|
|
217
|
+
// Check queue size
|
|
218
|
+
console.log('Queued messages:', getQueueSize());
|
|
172
219
|
|
|
173
|
-
|
|
220
|
+
// Clear queue if needed
|
|
221
|
+
flushQueue();
|
|
174
222
|
|
|
175
|
-
|
|
223
|
+
๐ Troubleshooting
|
|
224
|
+
Common Issues
|
|
176
225
|
|
|
177
|
-
|
|
226
|
+
CORS Errors with Local Development
|
|
227
|
+
javascript
|
|
178
228
|
|
|
179
|
-
|
|
229
|
+
// Ensure your WebSocket server allows connections from your origin
|
|
230
|
+
// For testing, use a public echo server:
|
|
231
|
+
url: 'wss://echo.websocket.org'
|
|
180
232
|
|
|
181
|
-
|
|
233
|
+
Connection Drops Frequently
|
|
234
|
+
javascript
|
|
182
235
|
|
|
183
|
-
|
|
184
|
-
|
|
236
|
+
// Enable heartbeat to keep connection alive
|
|
237
|
+
heartbeat: {
|
|
238
|
+
enabled: true,
|
|
239
|
+
interval: 15000, // Send ping every 15 seconds
|
|
240
|
+
}
|
|
185
241
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
RealtimeOptions,
|
|
189
|
-
ConnectionState,
|
|
190
|
-
UseRealtimeReturn
|
|
191
|
-
} from 'use-realtime';
|
|
242
|
+
Too Many Reconnect Attempts
|
|
243
|
+
javascript
|
|
192
244
|
|
|
193
|
-
|
|
245
|
+
// Limit reconnect attempts
|
|
246
|
+
reconnectAttempts: 5,
|
|
247
|
+
reconnectInterval: 5000, // Wait 5 seconds between attempts
|
|
194
248
|
|
|
195
|
-
|
|
249
|
+
๐ค Contributing
|
|
196
250
|
|
|
197
|
-
|
|
251
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
198
252
|
|
|
199
|
-
|
|
253
|
+
Fork the repository
|
|
200
254
|
|
|
201
|
-
|
|
255
|
+
Create your feature branch (git checkout -b feature/AmazingFeature)
|
|
202
256
|
|
|
203
|
-
|
|
257
|
+
Commit your changes (git commit -m 'Add some AmazingFeature')
|
|
204
258
|
|
|
205
|
-
|
|
259
|
+
Push to the branch (git push origin feature/AmazingFeature)
|
|
206
260
|
|
|
207
|
-
|
|
261
|
+
Open a Pull Request
|
|
208
262
|
|
|
209
|
-
|
|
263
|
+
๐ License
|
|
210
264
|
|
|
211
|
-
|
|
265
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
266
|
+
โญ Support
|
|
212
267
|
|
|
213
|
-
|
|
268
|
+
If you find this package useful, please consider:
|
|
214
269
|
|
|
215
|
-
|
|
216
|
-
<div align="center">
|
|
270
|
+
Giving it a star on GitHub
|
|
217
271
|
|
|
272
|
+
Sharing it with your colleagues
|
|
218
273
|
|
|
274
|
+
Reporting bugs or suggesting features
|
|
219
275
|
|
|
276
|
+
๐ Links
|
|
220
277
|
|
|
278
|
+
GitHub Repository
|
|
221
279
|
|
|
280
|
+
npm Package
|
|
222
281
|
|
|
282
|
+
Issue Tracker
|
package/package.json
CHANGED