react-realtime-hooks 1.1.0 → 1.2.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 +71 -4
- package/dist/index.cjs +237 -70
- 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 +237 -71
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -29,6 +29,34 @@ type UsePageVisibilityHook = (options?: UsePageVisibilityOptions) => UsePageVisi
|
|
|
29
29
|
|
|
30
30
|
declare const usePageVisibility: UsePageVisibilityHook;
|
|
31
31
|
|
|
32
|
+
type ConnectionGateReason = "ready" | "manual" | "offline" | "hidden";
|
|
33
|
+
interface UseConnectionGateOptions {
|
|
34
|
+
enabled?: boolean;
|
|
35
|
+
requireOnline?: boolean;
|
|
36
|
+
requireVisible?: boolean;
|
|
37
|
+
hiddenGraceMs?: number;
|
|
38
|
+
initialOnline?: boolean;
|
|
39
|
+
initialVisible?: boolean;
|
|
40
|
+
trackTransitions?: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface UseConnectionGateResult {
|
|
43
|
+
connect: boolean;
|
|
44
|
+
isBlocked: boolean;
|
|
45
|
+
isWaitingForVisibleGrace: boolean;
|
|
46
|
+
reason: ConnectionGateReason;
|
|
47
|
+
isOnline: boolean;
|
|
48
|
+
isOnlineSupported: boolean;
|
|
49
|
+
isVisible: boolean;
|
|
50
|
+
isVisibilitySupported: boolean;
|
|
51
|
+
visibilityState: DocumentVisibilityState | "visible";
|
|
52
|
+
lastChangedAt: number | null;
|
|
53
|
+
becameReadyAt: number | null;
|
|
54
|
+
becameBlockedAt: number | null;
|
|
55
|
+
}
|
|
56
|
+
type UseConnectionGateHook = (options?: UseConnectionGateOptions) => UseConnectionGateResult;
|
|
57
|
+
|
|
58
|
+
declare const useConnectionGate: UseConnectionGateHook;
|
|
59
|
+
|
|
32
60
|
type ReconnectStatus = "idle" | "scheduled" | "running" | "stopped";
|
|
33
61
|
type ReconnectTrigger = "mount" | "manual" | "close" | "error" | "heartbeat-timeout" | "offline" | "online" | "visibility";
|
|
34
62
|
interface ReconnectAttempt {
|
|
@@ -235,4 +263,4 @@ type UseEventSourceHook = <TMessage = unknown>(options: UseEventSourceOptions<TM
|
|
|
235
263
|
|
|
236
264
|
declare const useEventSource: UseEventSourceHook;
|
|
237
265
|
|
|
238
|
-
export { type ConnectionStateSnapshot, type HeartbeatAckMatcher, type HeartbeatBeatFn, type MessageParser, type MessageSerializer, type Milliseconds, type RealtimeConnectionStatus, type RealtimeTransport, type ReconnectAttempt, type ReconnectDelayContext, type ReconnectDelayStrategy, type ReconnectStatus, type ReconnectTrigger, type UrlProvider, type UseEventSourceHook, type UseEventSourceOptions, type UseEventSourceResult, type UseHeartbeatHook, type UseHeartbeatOptions, type UseHeartbeatResult, type UseOnlineStatusHook, type UseOnlineStatusOptions, type UseOnlineStatusResult, type UsePageVisibilityHook, type UsePageVisibilityOptions, type UsePageVisibilityResult, type UseReconnectHook, type UseReconnectOptions, type UseReconnectResult, type UseWebSocketHeartbeatOptions, type UseWebSocketHook, type UseWebSocketOptions, type UseWebSocketResult, type WebSocketHeartbeatAction, useEventSource, useHeartbeat, useOnlineStatus, usePageVisibility, useReconnect, useWebSocket };
|
|
266
|
+
export { type ConnectionGateReason, type ConnectionStateSnapshot, type HeartbeatAckMatcher, type HeartbeatBeatFn, type MessageParser, type MessageSerializer, type Milliseconds, type RealtimeConnectionStatus, type RealtimeTransport, type ReconnectAttempt, type ReconnectDelayContext, type ReconnectDelayStrategy, type ReconnectStatus, type ReconnectTrigger, type UrlProvider, type UseConnectionGateHook, type UseConnectionGateOptions, type UseConnectionGateResult, type UseEventSourceHook, type UseEventSourceOptions, type UseEventSourceResult, type UseHeartbeatHook, type UseHeartbeatOptions, type UseHeartbeatResult, type UseOnlineStatusHook, type UseOnlineStatusOptions, type UseOnlineStatusResult, type UsePageVisibilityHook, type UsePageVisibilityOptions, type UsePageVisibilityResult, type UseReconnectHook, type UseReconnectOptions, type UseReconnectResult, type UseWebSocketHeartbeatOptions, type UseWebSocketHook, type UseWebSocketOptions, type UseWebSocketResult, type WebSocketHeartbeatAction, useConnectionGate, useEventSource, useHeartbeat, useOnlineStatus, usePageVisibility, useReconnect, useWebSocket };
|
package/dist/index.js
CHANGED
|
@@ -136,6 +136,177 @@ var usePageVisibility = (options = {}) => {
|
|
|
136
136
|
};
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
+
// src/core/timers.ts
|
|
140
|
+
var sanitizeTimerDelay = (delayMs) => {
|
|
141
|
+
if (!Number.isFinite(delayMs)) {
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
return Math.max(0, Math.round(delayMs));
|
|
145
|
+
};
|
|
146
|
+
var createManagedTimeout = () => {
|
|
147
|
+
let timeoutId = null;
|
|
148
|
+
return {
|
|
149
|
+
cancel() {
|
|
150
|
+
if (timeoutId !== null) {
|
|
151
|
+
clearTimeout(timeoutId);
|
|
152
|
+
timeoutId = null;
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
isActive() {
|
|
156
|
+
return timeoutId !== null;
|
|
157
|
+
},
|
|
158
|
+
schedule(callback, delayMs) {
|
|
159
|
+
if (timeoutId !== null) {
|
|
160
|
+
clearTimeout(timeoutId);
|
|
161
|
+
}
|
|
162
|
+
timeoutId = setTimeout(() => {
|
|
163
|
+
timeoutId = null;
|
|
164
|
+
callback();
|
|
165
|
+
}, sanitizeTimerDelay(delayMs));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
var createManagedInterval = () => {
|
|
170
|
+
let intervalId = null;
|
|
171
|
+
return {
|
|
172
|
+
cancel() {
|
|
173
|
+
if (intervalId !== null) {
|
|
174
|
+
clearInterval(intervalId);
|
|
175
|
+
intervalId = null;
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
isActive() {
|
|
179
|
+
return intervalId !== null;
|
|
180
|
+
},
|
|
181
|
+
start(callback, intervalMs) {
|
|
182
|
+
if (intervalId !== null) {
|
|
183
|
+
clearInterval(intervalId);
|
|
184
|
+
}
|
|
185
|
+
intervalId = setInterval(callback, sanitizeTimerDelay(intervalMs));
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/hooks/useConnectionGate.ts
|
|
191
|
+
var createEmptyTransitionState3 = () => ({
|
|
192
|
+
becameBlockedAt: null,
|
|
193
|
+
becameReadyAt: null,
|
|
194
|
+
lastChangedAt: null
|
|
195
|
+
});
|
|
196
|
+
var normalizeHiddenGraceMs = (value) => {
|
|
197
|
+
if (value === void 0 || !Number.isFinite(value)) {
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
return Math.max(0, value);
|
|
201
|
+
};
|
|
202
|
+
var useConnectionGate = (options = {}) => {
|
|
203
|
+
const enabled = options.enabled ?? true;
|
|
204
|
+
const requireOnline = options.requireOnline ?? true;
|
|
205
|
+
const requireVisible = options.requireVisible ?? false;
|
|
206
|
+
const hiddenGraceMs = normalizeHiddenGraceMs(options.hiddenGraceMs);
|
|
207
|
+
const trackTransitions = options.trackTransitions ?? true;
|
|
208
|
+
const onlineStatus = useOnlineStatus({
|
|
209
|
+
...options.initialOnline === void 0 ? {} : { initialOnline: options.initialOnline },
|
|
210
|
+
trackTransitions: false
|
|
211
|
+
});
|
|
212
|
+
const pageVisibility = usePageVisibility({
|
|
213
|
+
...options.initialVisible === void 0 ? {} : { initialVisible: options.initialVisible },
|
|
214
|
+
trackTransitions: false
|
|
215
|
+
});
|
|
216
|
+
const hiddenGraceTimeoutRef = useRef(createManagedTimeout());
|
|
217
|
+
const hiddenSinceRef = useRef(null);
|
|
218
|
+
const previousStateRef = useRef(null);
|
|
219
|
+
const [hasExceededHiddenGrace, setHasExceededHiddenGrace] = useState(false);
|
|
220
|
+
const [isWaitingForVisibleGrace, setIsWaitingForVisibleGrace] = useState(false);
|
|
221
|
+
const [transitions, setTransitions] = useState(createEmptyTransitionState3);
|
|
222
|
+
useEffect(() => () => {
|
|
223
|
+
hiddenGraceTimeoutRef.current.cancel();
|
|
224
|
+
}, []);
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
hiddenGraceTimeoutRef.current.cancel();
|
|
227
|
+
if (!requireVisible || pageVisibility.isVisible) {
|
|
228
|
+
hiddenSinceRef.current = null;
|
|
229
|
+
setHasExceededHiddenGrace(false);
|
|
230
|
+
setIsWaitingForVisibleGrace(false);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const hiddenSince = hiddenSinceRef.current ?? Date.now();
|
|
234
|
+
hiddenSinceRef.current = hiddenSince;
|
|
235
|
+
if (hiddenGraceMs <= 0) {
|
|
236
|
+
setHasExceededHiddenGrace(true);
|
|
237
|
+
setIsWaitingForVisibleGrace(false);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const elapsedMs = Date.now() - hiddenSince;
|
|
241
|
+
if (elapsedMs >= hiddenGraceMs) {
|
|
242
|
+
setHasExceededHiddenGrace(true);
|
|
243
|
+
setIsWaitingForVisibleGrace(false);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
setHasExceededHiddenGrace(false);
|
|
247
|
+
setIsWaitingForVisibleGrace(true);
|
|
248
|
+
hiddenGraceTimeoutRef.current.schedule(() => {
|
|
249
|
+
setHasExceededHiddenGrace(true);
|
|
250
|
+
setIsWaitingForVisibleGrace(false);
|
|
251
|
+
}, hiddenGraceMs - elapsedMs);
|
|
252
|
+
}, [hiddenGraceMs, pageVisibility.isVisible, requireVisible]);
|
|
253
|
+
let reason = "ready";
|
|
254
|
+
if (!enabled) {
|
|
255
|
+
reason = "manual";
|
|
256
|
+
} else if (requireOnline && !onlineStatus.isOnline) {
|
|
257
|
+
reason = "offline";
|
|
258
|
+
} else if (requireVisible && !pageVisibility.isVisible && hasExceededHiddenGrace) {
|
|
259
|
+
reason = "hidden";
|
|
260
|
+
}
|
|
261
|
+
const connect = reason === "ready";
|
|
262
|
+
const isBlocked = !connect;
|
|
263
|
+
useEffect(() => {
|
|
264
|
+
if (!trackTransitions) {
|
|
265
|
+
previousStateRef.current = {
|
|
266
|
+
connect,
|
|
267
|
+
reason
|
|
268
|
+
};
|
|
269
|
+
setTransitions(createEmptyTransitionState3);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const previousState = previousStateRef.current;
|
|
273
|
+
if (previousState === null) {
|
|
274
|
+
previousStateRef.current = {
|
|
275
|
+
connect,
|
|
276
|
+
reason
|
|
277
|
+
};
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (previousState.connect === connect && previousState.reason === reason) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const changedAt = Date.now();
|
|
284
|
+
previousStateRef.current = {
|
|
285
|
+
connect,
|
|
286
|
+
reason
|
|
287
|
+
};
|
|
288
|
+
setTransitions((current) => ({
|
|
289
|
+
becameBlockedAt: connect ? current.becameBlockedAt : changedAt,
|
|
290
|
+
becameReadyAt: connect ? changedAt : current.becameReadyAt,
|
|
291
|
+
lastChangedAt: changedAt
|
|
292
|
+
}));
|
|
293
|
+
}, [connect, reason, trackTransitions]);
|
|
294
|
+
return {
|
|
295
|
+
becameBlockedAt: transitions.becameBlockedAt,
|
|
296
|
+
becameReadyAt: transitions.becameReadyAt,
|
|
297
|
+
connect,
|
|
298
|
+
isBlocked,
|
|
299
|
+
isOnline: onlineStatus.isOnline,
|
|
300
|
+
isOnlineSupported: onlineStatus.isSupported,
|
|
301
|
+
isVisibilitySupported: pageVisibility.isSupported,
|
|
302
|
+
isVisible: pageVisibility.isVisible,
|
|
303
|
+
isWaitingForVisibleGrace,
|
|
304
|
+
lastChangedAt: transitions.lastChangedAt,
|
|
305
|
+
reason,
|
|
306
|
+
visibilityState: pageVisibility.visibilityState
|
|
307
|
+
};
|
|
308
|
+
};
|
|
309
|
+
|
|
139
310
|
// src/core/reconnect.ts
|
|
140
311
|
var DEFAULT_RECONNECT_OPTIONS = {
|
|
141
312
|
backoffFactor: 2,
|
|
@@ -272,57 +443,6 @@ var createReconnectAttempt = (attempt, trigger, options, lastDelayMs, config = {
|
|
|
272
443
|
};
|
|
273
444
|
};
|
|
274
445
|
|
|
275
|
-
// src/core/timers.ts
|
|
276
|
-
var sanitizeTimerDelay = (delayMs) => {
|
|
277
|
-
if (!Number.isFinite(delayMs)) {
|
|
278
|
-
return 0;
|
|
279
|
-
}
|
|
280
|
-
return Math.max(0, Math.round(delayMs));
|
|
281
|
-
};
|
|
282
|
-
var createManagedTimeout = () => {
|
|
283
|
-
let timeoutId = null;
|
|
284
|
-
return {
|
|
285
|
-
cancel() {
|
|
286
|
-
if (timeoutId !== null) {
|
|
287
|
-
clearTimeout(timeoutId);
|
|
288
|
-
timeoutId = null;
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
|
-
isActive() {
|
|
292
|
-
return timeoutId !== null;
|
|
293
|
-
},
|
|
294
|
-
schedule(callback, delayMs) {
|
|
295
|
-
if (timeoutId !== null) {
|
|
296
|
-
clearTimeout(timeoutId);
|
|
297
|
-
}
|
|
298
|
-
timeoutId = setTimeout(() => {
|
|
299
|
-
timeoutId = null;
|
|
300
|
-
callback();
|
|
301
|
-
}, sanitizeTimerDelay(delayMs));
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
};
|
|
305
|
-
var createManagedInterval = () => {
|
|
306
|
-
let intervalId = null;
|
|
307
|
-
return {
|
|
308
|
-
cancel() {
|
|
309
|
-
if (intervalId !== null) {
|
|
310
|
-
clearInterval(intervalId);
|
|
311
|
-
intervalId = null;
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
isActive() {
|
|
315
|
-
return intervalId !== null;
|
|
316
|
-
},
|
|
317
|
-
start(callback, intervalMs) {
|
|
318
|
-
if (intervalId !== null) {
|
|
319
|
-
clearInterval(intervalId);
|
|
320
|
-
}
|
|
321
|
-
intervalId = setInterval(callback, sanitizeTimerDelay(intervalMs));
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
};
|
|
325
|
-
|
|
326
446
|
// src/hooks/useReconnect.ts
|
|
327
447
|
var createInitialState = (enabled) => ({
|
|
328
448
|
attempt: 0,
|
|
@@ -704,6 +824,9 @@ var useWebSocket = (options) => {
|
|
|
704
824
|
const protocolsDependency = toProtocolsDependency(options.protocols);
|
|
705
825
|
const socketRef = useRef(null);
|
|
706
826
|
const socketKeyRef = useRef(null);
|
|
827
|
+
const activeSocketEpochRef = useRef(null);
|
|
828
|
+
const closingSocketEpochRef = useRef(null);
|
|
829
|
+
const nextSocketEpochRef = useRef(0);
|
|
707
830
|
const manualCloseRef = useRef(false);
|
|
708
831
|
const manualOpenRef = useRef(false);
|
|
709
832
|
const skipCloseReconnectRef = useRef(false);
|
|
@@ -792,17 +915,28 @@ var useWebSocket = (options) => {
|
|
|
792
915
|
stateRef.current = resolved;
|
|
793
916
|
setState(resolved);
|
|
794
917
|
};
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
if (socket2 === null) {
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
socketRef.current = null;
|
|
801
|
-
socketKeyRef.current = null;
|
|
802
|
-
if (isSocketActive(socket2)) {
|
|
803
|
-
socket2.close(code, reason);
|
|
804
|
-
}
|
|
918
|
+
const isActiveSocketEvent = useEffectEvent((socketEpoch) => {
|
|
919
|
+
return activeSocketEpochRef.current === socketEpoch;
|
|
805
920
|
});
|
|
921
|
+
const shouldHandleSocketClose = useEffectEvent((socketEpoch) => {
|
|
922
|
+
return activeSocketEpochRef.current === socketEpoch || closingSocketEpochRef.current === socketEpoch;
|
|
923
|
+
});
|
|
924
|
+
const closeSocket = useEffectEvent(
|
|
925
|
+
(config = {}) => {
|
|
926
|
+
const socket2 = socketRef.current;
|
|
927
|
+
const socketEpoch = activeSocketEpochRef.current;
|
|
928
|
+
if (socket2 === null || socketEpoch === null) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
socketRef.current = null;
|
|
932
|
+
socketKeyRef.current = null;
|
|
933
|
+
activeSocketEpochRef.current = null;
|
|
934
|
+
closingSocketEpochRef.current = config.trackClose ? socketEpoch : null;
|
|
935
|
+
if (isSocketActive(socket2)) {
|
|
936
|
+
socket2.close(config.code, config.reason);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
);
|
|
806
940
|
const applyHeartbeatAction = useEffectEvent(
|
|
807
941
|
(action, error, reconnectTrigger) => {
|
|
808
942
|
heartbeat.stop();
|
|
@@ -837,7 +971,7 @@ var useWebSocket = (options) => {
|
|
|
837
971
|
};
|
|
838
972
|
skipCloseReconnectRef.current = true;
|
|
839
973
|
suppressReconnectRef.current = true;
|
|
840
|
-
closeSocket();
|
|
974
|
+
closeSocket({ trackClose: true });
|
|
841
975
|
}
|
|
842
976
|
);
|
|
843
977
|
const parseMessage = useEffectEvent((event) => {
|
|
@@ -891,10 +1025,17 @@ var useWebSocket = (options) => {
|
|
|
891
1025
|
lastError: parseError,
|
|
892
1026
|
status: "error"
|
|
893
1027
|
}));
|
|
894
|
-
closeSocket(
|
|
1028
|
+
closeSocket({
|
|
1029
|
+
code: 1003,
|
|
1030
|
+
reason: "parse-error",
|
|
1031
|
+
trackClose: true
|
|
1032
|
+
});
|
|
895
1033
|
}
|
|
896
1034
|
});
|
|
897
|
-
const handleError = useEffectEvent((event) => {
|
|
1035
|
+
const handleError = useEffectEvent((event, socketEpoch) => {
|
|
1036
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
898
1039
|
heartbeat.stop();
|
|
899
1040
|
commitState((current) => ({
|
|
900
1041
|
...current,
|
|
@@ -904,9 +1045,18 @@ var useWebSocket = (options) => {
|
|
|
904
1045
|
}));
|
|
905
1046
|
options.onError?.(event);
|
|
906
1047
|
});
|
|
907
|
-
const handleClose = useEffectEvent((event) => {
|
|
908
|
-
|
|
909
|
-
|
|
1048
|
+
const handleClose = useEffectEvent((event, socketEpoch) => {
|
|
1049
|
+
if (!shouldHandleSocketClose(socketEpoch)) {
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
if (activeSocketEpochRef.current === socketEpoch) {
|
|
1053
|
+
socketRef.current = null;
|
|
1054
|
+
socketKeyRef.current = null;
|
|
1055
|
+
activeSocketEpochRef.current = null;
|
|
1056
|
+
}
|
|
1057
|
+
if (closingSocketEpochRef.current === socketEpoch) {
|
|
1058
|
+
closingSocketEpochRef.current = null;
|
|
1059
|
+
}
|
|
910
1060
|
heartbeat.stop();
|
|
911
1061
|
updateBufferedAmount();
|
|
912
1062
|
const pendingCloseAction = pendingCloseActionRef.current;
|
|
@@ -986,7 +1136,11 @@ var useWebSocket = (options) => {
|
|
|
986
1136
|
lastChangedAt: Date.now(),
|
|
987
1137
|
status: "closing"
|
|
988
1138
|
}));
|
|
989
|
-
closeSocket(
|
|
1139
|
+
closeSocket({
|
|
1140
|
+
code,
|
|
1141
|
+
reason,
|
|
1142
|
+
trackClose: true
|
|
1143
|
+
});
|
|
990
1144
|
};
|
|
991
1145
|
const send = (message) => {
|
|
992
1146
|
const socket2 = socketRef.current;
|
|
@@ -1038,8 +1192,12 @@ var useWebSocket = (options) => {
|
|
|
1038
1192
|
return;
|
|
1039
1193
|
}
|
|
1040
1194
|
const socket2 = new WebSocket(resolvedUrl, options.protocols);
|
|
1195
|
+
const socketEpoch = nextSocketEpochRef.current + 1;
|
|
1041
1196
|
socketRef.current = socket2;
|
|
1042
1197
|
socketKeyRef.current = nextSocketKey;
|
|
1198
|
+
activeSocketEpochRef.current = socketEpoch;
|
|
1199
|
+
closingSocketEpochRef.current = null;
|
|
1200
|
+
nextSocketEpochRef.current = socketEpoch;
|
|
1043
1201
|
socket2.binaryType = options.binaryType ?? "blob";
|
|
1044
1202
|
commitState((current) => ({
|
|
1045
1203
|
...current,
|
|
@@ -1048,16 +1206,22 @@ var useWebSocket = (options) => {
|
|
|
1048
1206
|
status: reconnect.status === "running" || reconnect.status === "scheduled" ? "reconnecting" : "connecting"
|
|
1049
1207
|
}));
|
|
1050
1208
|
const handleSocketOpen = (event) => {
|
|
1209
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1051
1212
|
handleOpen(event, socket2);
|
|
1052
1213
|
};
|
|
1053
1214
|
const handleSocketMessage = (event) => {
|
|
1215
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1054
1218
|
handleMessage(event);
|
|
1055
1219
|
};
|
|
1056
1220
|
const handleSocketError = (event) => {
|
|
1057
|
-
handleError(event);
|
|
1221
|
+
handleError(event, socketEpoch);
|
|
1058
1222
|
};
|
|
1059
1223
|
const handleSocketClose = (event) => {
|
|
1060
|
-
handleClose(event);
|
|
1224
|
+
handleClose(event, socketEpoch);
|
|
1061
1225
|
};
|
|
1062
1226
|
socket2.addEventListener("open", handleSocketOpen);
|
|
1063
1227
|
socket2.addEventListener("message", handleSocketMessage);
|
|
@@ -1081,6 +1245,8 @@ var useWebSocket = (options) => {
|
|
|
1081
1245
|
useEffect(() => () => {
|
|
1082
1246
|
suppressReconnectRef.current = true;
|
|
1083
1247
|
socketKeyRef.current = null;
|
|
1248
|
+
activeSocketEpochRef.current = null;
|
|
1249
|
+
closingSocketEpochRef.current = null;
|
|
1084
1250
|
terminalErrorRef.current = null;
|
|
1085
1251
|
const socket2 = socketRef.current;
|
|
1086
1252
|
socketRef.current = null;
|
|
@@ -1458,6 +1624,6 @@ var useEventSource = (options) => {
|
|
|
1458
1624
|
};
|
|
1459
1625
|
};
|
|
1460
1626
|
|
|
1461
|
-
export { useEventSource, useHeartbeat, useOnlineStatus, usePageVisibility, useReconnect, useWebSocket };
|
|
1627
|
+
export { useConnectionGate, useEventSource, useHeartbeat, useOnlineStatus, usePageVisibility, useReconnect, useWebSocket };
|
|
1462
1628
|
//# sourceMappingURL=index.js.map
|
|
1463
1629
|
//# sourceMappingURL=index.js.map
|