react-realtime-hooks 2.0.1 → 2.0.3
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 +1 -0
- package/dist/index.cjs +37 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +37 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://github.com/volkov85/react-realtime-hooks/blob/main/LICENSE)
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
10
|
[](https://www.npmjs.com/package/react)
|
|
11
|
+
[](https://www.react.doctor/share?p=react-realtime-hooks&s=94&e=2&w=28&f=21)
|
|
11
12
|
|
|
12
13
|
Production-ready React hooks for WebSocket and SSE with auto-reconnect, heartbeat, typed connection state, and browser network awareness including page visibility and connection gating.
|
|
13
14
|
|
package/dist/index.cjs
CHANGED
|
@@ -939,6 +939,7 @@ var useWebSocket = (options) => {
|
|
|
939
939
|
[protocolsDependency]
|
|
940
940
|
);
|
|
941
941
|
const socketRef = react.useRef(null);
|
|
942
|
+
const detachSocketListenersRef = react.useRef(null);
|
|
942
943
|
const socketKeyRef = react.useRef(null);
|
|
943
944
|
const activeSocketEpochRef = react.useRef(null);
|
|
944
945
|
const closingSocketEpochRef = react.useRef(null);
|
|
@@ -1051,6 +1052,10 @@ var useWebSocket = (options) => {
|
|
|
1051
1052
|
socketKeyRef.current = null;
|
|
1052
1053
|
activeSocketEpochRef.current = null;
|
|
1053
1054
|
closingSocketEpochRef.current = config.trackClose ? socketEpoch : null;
|
|
1055
|
+
if (!config.trackClose) {
|
|
1056
|
+
detachSocketListenersRef.current?.();
|
|
1057
|
+
detachSocketListenersRef.current = null;
|
|
1058
|
+
}
|
|
1054
1059
|
if (isSocketActive(socket2)) {
|
|
1055
1060
|
socket2.close(config.code, config.reason);
|
|
1056
1061
|
}
|
|
@@ -1162,6 +1167,8 @@ var useWebSocket = (options) => {
|
|
|
1162
1167
|
if (!shouldHandleSocketClose(socketEpoch)) {
|
|
1163
1168
|
return;
|
|
1164
1169
|
}
|
|
1170
|
+
detachSocketListenersRef.current?.();
|
|
1171
|
+
detachSocketListenersRef.current = null;
|
|
1165
1172
|
if (activeSocketEpochRef.current === socketEpoch) {
|
|
1166
1173
|
socketRef.current = null;
|
|
1167
1174
|
socketKeyRef.current = null;
|
|
@@ -1232,10 +1239,12 @@ var useWebSocket = (options) => {
|
|
|
1232
1239
|
controller.noteUserCloseRequested();
|
|
1233
1240
|
reconnect.cancel();
|
|
1234
1241
|
heartbeat.stop();
|
|
1242
|
+
const socket2 = socketRef.current;
|
|
1243
|
+
const hasInFlightSocket = socket2 !== null && (socket2.readyState === WebSocket.CONNECTING || socket2.readyState === WebSocket.OPEN);
|
|
1235
1244
|
commitState((current) => ({
|
|
1236
1245
|
...current,
|
|
1237
1246
|
lastChangedAt: Date.now(),
|
|
1238
|
-
status: "closing"
|
|
1247
|
+
status: hasInFlightSocket ? "closing" : "closed"
|
|
1239
1248
|
}));
|
|
1240
1249
|
closeSocket({
|
|
1241
1250
|
code,
|
|
@@ -1299,12 +1308,21 @@ var useWebSocket = (options) => {
|
|
|
1299
1308
|
status: reconnect.status === "running" || reconnect.status === "scheduled" ? "reconnecting" : "connecting"
|
|
1300
1309
|
}));
|
|
1301
1310
|
let cancelled = false;
|
|
1302
|
-
let detachListeners = null;
|
|
1303
1311
|
queueMicrotask(() => {
|
|
1304
1312
|
if (cancelled) {
|
|
1305
1313
|
return;
|
|
1306
1314
|
}
|
|
1315
|
+
if (controller.hasManualCloseRequested()) {
|
|
1316
|
+
commitState((current) => ({
|
|
1317
|
+
...current,
|
|
1318
|
+
lastChangedAt: Date.now(),
|
|
1319
|
+
status: "closed"
|
|
1320
|
+
}));
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1307
1323
|
const socket2 = new WebSocket(resolvedUrl, protocols);
|
|
1324
|
+
detachSocketListenersRef.current?.();
|
|
1325
|
+
detachSocketListenersRef.current = null;
|
|
1308
1326
|
const socketEpoch = nextSocketEpochRef.current + 1;
|
|
1309
1327
|
socketRef.current = socket2;
|
|
1310
1328
|
socketKeyRef.current = nextSocketKey;
|
|
@@ -1338,7 +1356,7 @@ var useWebSocket = (options) => {
|
|
|
1338
1356
|
socket2.addEventListener("message", handleSocketMessage);
|
|
1339
1357
|
socket2.addEventListener("error", handleSocketError);
|
|
1340
1358
|
socket2.addEventListener("close", handleSocketClose);
|
|
1341
|
-
|
|
1359
|
+
detachSocketListenersRef.current = () => {
|
|
1342
1360
|
socket2.removeEventListener("open", handleSocketOpen);
|
|
1343
1361
|
socket2.removeEventListener("message", handleSocketMessage);
|
|
1344
1362
|
socket2.removeEventListener("error", handleSocketError);
|
|
@@ -1347,7 +1365,6 @@ var useWebSocket = (options) => {
|
|
|
1347
1365
|
});
|
|
1348
1366
|
return () => {
|
|
1349
1367
|
cancelled = true;
|
|
1350
|
-
detachListeners?.();
|
|
1351
1368
|
};
|
|
1352
1369
|
}, [
|
|
1353
1370
|
closeSocket,
|
|
@@ -1368,6 +1385,8 @@ var useWebSocket = (options) => {
|
|
|
1368
1385
|
supported
|
|
1369
1386
|
]);
|
|
1370
1387
|
react.useEffect(() => () => {
|
|
1388
|
+
detachSocketListenersRef.current?.();
|
|
1389
|
+
detachSocketListenersRef.current = null;
|
|
1371
1390
|
controller.noteEffectInitiatedClose();
|
|
1372
1391
|
socketKeyRef.current = null;
|
|
1373
1392
|
activeSocketEpochRef.current = null;
|
|
@@ -1512,6 +1531,7 @@ var useEventSource = (options) => {
|
|
|
1512
1531
|
[eventsDependency]
|
|
1513
1532
|
);
|
|
1514
1533
|
const eventSourceRef = react.useRef(null);
|
|
1534
|
+
const detachEventSourceListenersRef = react.useRef(null);
|
|
1515
1535
|
const eventSourceKeyRef = react.useRef(null);
|
|
1516
1536
|
const activeEventSourceEpochRef = react.useRef(null);
|
|
1517
1537
|
const nextEventSourceEpochRef = react.useRef(0);
|
|
@@ -1549,6 +1569,8 @@ var useEventSource = (options) => {
|
|
|
1549
1569
|
eventSourceRef.current = null;
|
|
1550
1570
|
eventSourceKeyRef.current = null;
|
|
1551
1571
|
activeEventSourceEpochRef.current = null;
|
|
1572
|
+
detachEventSourceListenersRef.current?.();
|
|
1573
|
+
detachEventSourceListenersRef.current = null;
|
|
1552
1574
|
source.close();
|
|
1553
1575
|
});
|
|
1554
1576
|
const isActiveEventSourceEvent = useStableCallback((sourceEpoch) => {
|
|
@@ -1719,11 +1741,18 @@ var useEventSource = (options) => {
|
|
|
1719
1741
|
status: reconnect.status === "running" || reconnect.status === "scheduled" ? "reconnecting" : "connecting"
|
|
1720
1742
|
}));
|
|
1721
1743
|
let cancelled = false;
|
|
1722
|
-
let detachListeners = null;
|
|
1723
1744
|
queueMicrotask(() => {
|
|
1724
1745
|
if (cancelled) {
|
|
1725
1746
|
return;
|
|
1726
1747
|
}
|
|
1748
|
+
if (manualCloseRef.current) {
|
|
1749
|
+
commitState((current) => ({
|
|
1750
|
+
...current,
|
|
1751
|
+
lastChangedAt: Date.now(),
|
|
1752
|
+
status: "closed"
|
|
1753
|
+
}));
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1727
1756
|
const source = new EventSource(resolvedUrl, {
|
|
1728
1757
|
withCredentials: options.withCredentials ?? false
|
|
1729
1758
|
});
|
|
@@ -1761,7 +1790,7 @@ var useEventSource = (options) => {
|
|
|
1761
1790
|
source.addEventListener(eventName, handler);
|
|
1762
1791
|
}
|
|
1763
1792
|
source.addEventListener("error", handleSourceError);
|
|
1764
|
-
|
|
1793
|
+
detachEventSourceListenersRef.current = () => {
|
|
1765
1794
|
source.removeEventListener("open", handleSourceOpen);
|
|
1766
1795
|
source.removeEventListener("message", handleSourceMessage);
|
|
1767
1796
|
for (const [eventName, handler] of namedEventHandlers) {
|
|
@@ -1772,7 +1801,6 @@ var useEventSource = (options) => {
|
|
|
1772
1801
|
});
|
|
1773
1802
|
return () => {
|
|
1774
1803
|
cancelled = true;
|
|
1775
|
-
detachListeners?.();
|
|
1776
1804
|
};
|
|
1777
1805
|
}, [
|
|
1778
1806
|
closeEventSource,
|
|
@@ -1791,6 +1819,8 @@ var useEventSource = (options) => {
|
|
|
1791
1819
|
supported
|
|
1792
1820
|
]);
|
|
1793
1821
|
react.useEffect(() => () => {
|
|
1822
|
+
detachEventSourceListenersRef.current?.();
|
|
1823
|
+
detachEventSourceListenersRef.current = null;
|
|
1794
1824
|
suppressReconnectRef.current = true;
|
|
1795
1825
|
eventSourceKeyRef.current = null;
|
|
1796
1826
|
activeEventSourceEpochRef.current = null;
|