react-realtime-hooks 1.3.4 → 1.4.0
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 +17 -1
- package/dist/index.cjs +52 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -257,6 +257,21 @@ export function ChatSocket() {
|
|
|
257
257
|
}
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
+
The native `WebSocket` does not emit any event when buffered bytes drain to the network, so by default `bufferedAmount` only refreshes on `send()`, on incoming messages, and on the `open` transition. Pass `bufferedAmountPolling` to surface the live value for backpressure indicators:
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
const socket = useWebSocket<IncomingMessage, OutgoingMessage>({
|
|
264
|
+
url: "ws://localhost:8080",
|
|
265
|
+
// "raf" reads `bufferedAmount` on every animation frame while open;
|
|
266
|
+
// use `true` for a 100ms interval, or `{ intervalMs: 50 }` for custom.
|
|
267
|
+
bufferedAmountPolling: "raf",
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// `socket.bufferedAmount` now ticks down as the OS flushes the buffer,
|
|
271
|
+
// even between `send` calls. Identical readings do not trigger React
|
|
272
|
+
// re-renders.
|
|
273
|
+
```
|
|
274
|
+
|
|
260
275
|
### `useEventSource`
|
|
261
276
|
|
|
262
277
|
```tsx
|
|
@@ -400,6 +415,7 @@ export function GatedNotifications() {
|
|
|
400
415
|
| `protocols` | `string \| string[]` | `undefined` | WebSocket subprotocols |
|
|
401
416
|
| `connect` | `boolean` | `true` | Auto-connect on mount |
|
|
402
417
|
| `binaryType` | `BinaryType` | `"blob"` | Socket binary mode |
|
|
418
|
+
| `bufferedAmountPolling` | `false \| true \| "raf" \| { intervalMs: number }` | `false` | Live polling of `WebSocket.bufferedAmount` for backpressure UIs |
|
|
403
419
|
| `parseMessage` | `(event) => TIncoming` | raw `event.data` | Incoming parser |
|
|
404
420
|
| `serializeMessage` | `(message) => ...` | JSON/string passthrough | Outgoing serializer |
|
|
405
421
|
| `reconnect` | `false \| UseReconnectOptions` | enabled | Reconnect configuration |
|
|
@@ -420,7 +436,7 @@ export function GatedNotifications() {
|
|
|
420
436
|
| `lastMessageEvent` | `MessageEvent \| null` | Last raw message event |
|
|
421
437
|
| `lastCloseEvent` | `CloseEvent \| null` | Last close event |
|
|
422
438
|
| `lastError` | `Event \| null` | Last transport error, or `RealtimeErrorEvent` for parse/heartbeat failures |
|
|
423
|
-
| `bufferedAmount` | `number` | Current socket buffer size
|
|
439
|
+
| `bufferedAmount` | `number` | Current socket buffer size (refresh cadence is controlled by `bufferedAmountPolling`) |
|
|
424
440
|
| `reconnectState` | reconnect snapshot or `null` | Current reconnect data |
|
|
425
441
|
| `heartbeatState` | heartbeat snapshot or `null` | Current heartbeat data |
|
|
426
442
|
| `open` | `() => void` | Manual connect |
|
package/dist/index.cjs
CHANGED
|
@@ -1317,6 +1317,58 @@ var useWebSocket = (options) => {
|
|
|
1317
1317
|
stopHeartbeat();
|
|
1318
1318
|
}
|
|
1319
1319
|
}, [state.status, stopHeartbeat]);
|
|
1320
|
+
const rawBufferedAmountPolling = options.bufferedAmountPolling;
|
|
1321
|
+
const bufferedAmountPollingMode = react.useMemo(() => {
|
|
1322
|
+
if (rawBufferedAmountPolling === void 0 || rawBufferedAmountPolling === false) {
|
|
1323
|
+
return null;
|
|
1324
|
+
}
|
|
1325
|
+
if (rawBufferedAmountPolling === true) {
|
|
1326
|
+
return 100;
|
|
1327
|
+
}
|
|
1328
|
+
if (rawBufferedAmountPolling === "raf") {
|
|
1329
|
+
return "raf";
|
|
1330
|
+
}
|
|
1331
|
+
const intervalMs = rawBufferedAmountPolling.intervalMs;
|
|
1332
|
+
return Number.isFinite(intervalMs) && intervalMs > 0 ? intervalMs : null;
|
|
1333
|
+
}, [rawBufferedAmountPolling]);
|
|
1334
|
+
const pollBufferedAmount = useStableCallback(() => {
|
|
1335
|
+
const socket2 = socketRef.current;
|
|
1336
|
+
if (socket2 === null) {
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
const next = socket2.bufferedAmount;
|
|
1340
|
+
if (stateRef.current.bufferedAmount === next) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
commitState((current) => ({
|
|
1344
|
+
...current,
|
|
1345
|
+
bufferedAmount: next
|
|
1346
|
+
}));
|
|
1347
|
+
});
|
|
1348
|
+
react.useEffect(() => {
|
|
1349
|
+
if (bufferedAmountPollingMode === null) {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
if (state.status !== "open") {
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
if (bufferedAmountPollingMode === "raf") {
|
|
1356
|
+
if (typeof requestAnimationFrame !== "function") {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
let frame = requestAnimationFrame(function loop() {
|
|
1360
|
+
pollBufferedAmount();
|
|
1361
|
+
frame = requestAnimationFrame(loop);
|
|
1362
|
+
});
|
|
1363
|
+
return () => {
|
|
1364
|
+
cancelAnimationFrame(frame);
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
const intervalId = setInterval(pollBufferedAmount, bufferedAmountPollingMode);
|
|
1368
|
+
return () => {
|
|
1369
|
+
clearInterval(intervalId);
|
|
1370
|
+
};
|
|
1371
|
+
}, [bufferedAmountPollingMode, state.status, pollBufferedAmount]);
|
|
1320
1372
|
const status = (reconnect.status === "scheduled" || reconnect.status === "running") && state.status !== "open" ? "reconnecting" : state.status;
|
|
1321
1373
|
const snapshot = createConnectionStateSnapshot(status, {
|
|
1322
1374
|
isSupported: supported,
|