react-realtime-hooks 1.2.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/dist/index.cjs +65 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +65 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -826,6 +826,9 @@ var useWebSocket = (options) => {
|
|
|
826
826
|
const protocolsDependency = toProtocolsDependency(options.protocols);
|
|
827
827
|
const socketRef = react.useRef(null);
|
|
828
828
|
const socketKeyRef = react.useRef(null);
|
|
829
|
+
const activeSocketEpochRef = react.useRef(null);
|
|
830
|
+
const closingSocketEpochRef = react.useRef(null);
|
|
831
|
+
const nextSocketEpochRef = react.useRef(0);
|
|
829
832
|
const manualCloseRef = react.useRef(false);
|
|
830
833
|
const manualOpenRef = react.useRef(false);
|
|
831
834
|
const skipCloseReconnectRef = react.useRef(false);
|
|
@@ -914,17 +917,28 @@ var useWebSocket = (options) => {
|
|
|
914
917
|
stateRef.current = resolved;
|
|
915
918
|
setState(resolved);
|
|
916
919
|
};
|
|
917
|
-
const
|
|
918
|
-
|
|
919
|
-
if (socket2 === null) {
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
|
-
socketRef.current = null;
|
|
923
|
-
socketKeyRef.current = null;
|
|
924
|
-
if (isSocketActive(socket2)) {
|
|
925
|
-
socket2.close(code, reason);
|
|
926
|
-
}
|
|
920
|
+
const isActiveSocketEvent = react.useEffectEvent((socketEpoch) => {
|
|
921
|
+
return activeSocketEpochRef.current === socketEpoch;
|
|
927
922
|
});
|
|
923
|
+
const shouldHandleSocketClose = react.useEffectEvent((socketEpoch) => {
|
|
924
|
+
return activeSocketEpochRef.current === socketEpoch || closingSocketEpochRef.current === socketEpoch;
|
|
925
|
+
});
|
|
926
|
+
const closeSocket = react.useEffectEvent(
|
|
927
|
+
(config = {}) => {
|
|
928
|
+
const socket2 = socketRef.current;
|
|
929
|
+
const socketEpoch = activeSocketEpochRef.current;
|
|
930
|
+
if (socket2 === null || socketEpoch === null) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
socketRef.current = null;
|
|
934
|
+
socketKeyRef.current = null;
|
|
935
|
+
activeSocketEpochRef.current = null;
|
|
936
|
+
closingSocketEpochRef.current = config.trackClose ? socketEpoch : null;
|
|
937
|
+
if (isSocketActive(socket2)) {
|
|
938
|
+
socket2.close(config.code, config.reason);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
);
|
|
928
942
|
const applyHeartbeatAction = react.useEffectEvent(
|
|
929
943
|
(action, error, reconnectTrigger) => {
|
|
930
944
|
heartbeat.stop();
|
|
@@ -959,7 +973,7 @@ var useWebSocket = (options) => {
|
|
|
959
973
|
};
|
|
960
974
|
skipCloseReconnectRef.current = true;
|
|
961
975
|
suppressReconnectRef.current = true;
|
|
962
|
-
closeSocket();
|
|
976
|
+
closeSocket({ trackClose: true });
|
|
963
977
|
}
|
|
964
978
|
);
|
|
965
979
|
const parseMessage = react.useEffectEvent((event) => {
|
|
@@ -1013,10 +1027,17 @@ var useWebSocket = (options) => {
|
|
|
1013
1027
|
lastError: parseError,
|
|
1014
1028
|
status: "error"
|
|
1015
1029
|
}));
|
|
1016
|
-
closeSocket(
|
|
1030
|
+
closeSocket({
|
|
1031
|
+
code: 1003,
|
|
1032
|
+
reason: "parse-error",
|
|
1033
|
+
trackClose: true
|
|
1034
|
+
});
|
|
1017
1035
|
}
|
|
1018
1036
|
});
|
|
1019
|
-
const handleError = react.useEffectEvent((event) => {
|
|
1037
|
+
const handleError = react.useEffectEvent((event, socketEpoch) => {
|
|
1038
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1020
1041
|
heartbeat.stop();
|
|
1021
1042
|
commitState((current) => ({
|
|
1022
1043
|
...current,
|
|
@@ -1026,9 +1047,18 @@ var useWebSocket = (options) => {
|
|
|
1026
1047
|
}));
|
|
1027
1048
|
options.onError?.(event);
|
|
1028
1049
|
});
|
|
1029
|
-
const handleClose = react.useEffectEvent((event) => {
|
|
1030
|
-
|
|
1031
|
-
|
|
1050
|
+
const handleClose = react.useEffectEvent((event, socketEpoch) => {
|
|
1051
|
+
if (!shouldHandleSocketClose(socketEpoch)) {
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if (activeSocketEpochRef.current === socketEpoch) {
|
|
1055
|
+
socketRef.current = null;
|
|
1056
|
+
socketKeyRef.current = null;
|
|
1057
|
+
activeSocketEpochRef.current = null;
|
|
1058
|
+
}
|
|
1059
|
+
if (closingSocketEpochRef.current === socketEpoch) {
|
|
1060
|
+
closingSocketEpochRef.current = null;
|
|
1061
|
+
}
|
|
1032
1062
|
heartbeat.stop();
|
|
1033
1063
|
updateBufferedAmount();
|
|
1034
1064
|
const pendingCloseAction = pendingCloseActionRef.current;
|
|
@@ -1108,7 +1138,11 @@ var useWebSocket = (options) => {
|
|
|
1108
1138
|
lastChangedAt: Date.now(),
|
|
1109
1139
|
status: "closing"
|
|
1110
1140
|
}));
|
|
1111
|
-
closeSocket(
|
|
1141
|
+
closeSocket({
|
|
1142
|
+
code,
|
|
1143
|
+
reason,
|
|
1144
|
+
trackClose: true
|
|
1145
|
+
});
|
|
1112
1146
|
};
|
|
1113
1147
|
const send = (message) => {
|
|
1114
1148
|
const socket2 = socketRef.current;
|
|
@@ -1160,8 +1194,12 @@ var useWebSocket = (options) => {
|
|
|
1160
1194
|
return;
|
|
1161
1195
|
}
|
|
1162
1196
|
const socket2 = new WebSocket(resolvedUrl, options.protocols);
|
|
1197
|
+
const socketEpoch = nextSocketEpochRef.current + 1;
|
|
1163
1198
|
socketRef.current = socket2;
|
|
1164
1199
|
socketKeyRef.current = nextSocketKey;
|
|
1200
|
+
activeSocketEpochRef.current = socketEpoch;
|
|
1201
|
+
closingSocketEpochRef.current = null;
|
|
1202
|
+
nextSocketEpochRef.current = socketEpoch;
|
|
1165
1203
|
socket2.binaryType = options.binaryType ?? "blob";
|
|
1166
1204
|
commitState((current) => ({
|
|
1167
1205
|
...current,
|
|
@@ -1170,16 +1208,22 @@ var useWebSocket = (options) => {
|
|
|
1170
1208
|
status: reconnect.status === "running" || reconnect.status === "scheduled" ? "reconnecting" : "connecting"
|
|
1171
1209
|
}));
|
|
1172
1210
|
const handleSocketOpen = (event) => {
|
|
1211
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1173
1214
|
handleOpen(event, socket2);
|
|
1174
1215
|
};
|
|
1175
1216
|
const handleSocketMessage = (event) => {
|
|
1217
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1176
1220
|
handleMessage(event);
|
|
1177
1221
|
};
|
|
1178
1222
|
const handleSocketError = (event) => {
|
|
1179
|
-
handleError(event);
|
|
1223
|
+
handleError(event, socketEpoch);
|
|
1180
1224
|
};
|
|
1181
1225
|
const handleSocketClose = (event) => {
|
|
1182
|
-
handleClose(event);
|
|
1226
|
+
handleClose(event, socketEpoch);
|
|
1183
1227
|
};
|
|
1184
1228
|
socket2.addEventListener("open", handleSocketOpen);
|
|
1185
1229
|
socket2.addEventListener("message", handleSocketMessage);
|
|
@@ -1203,6 +1247,8 @@ var useWebSocket = (options) => {
|
|
|
1203
1247
|
react.useEffect(() => () => {
|
|
1204
1248
|
suppressReconnectRef.current = true;
|
|
1205
1249
|
socketKeyRef.current = null;
|
|
1250
|
+
activeSocketEpochRef.current = null;
|
|
1251
|
+
closingSocketEpochRef.current = null;
|
|
1206
1252
|
terminalErrorRef.current = null;
|
|
1207
1253
|
const socket2 = socketRef.current;
|
|
1208
1254
|
socketRef.current = null;
|