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.js
CHANGED
|
@@ -824,6 +824,9 @@ var useWebSocket = (options) => {
|
|
|
824
824
|
const protocolsDependency = toProtocolsDependency(options.protocols);
|
|
825
825
|
const socketRef = useRef(null);
|
|
826
826
|
const socketKeyRef = useRef(null);
|
|
827
|
+
const activeSocketEpochRef = useRef(null);
|
|
828
|
+
const closingSocketEpochRef = useRef(null);
|
|
829
|
+
const nextSocketEpochRef = useRef(0);
|
|
827
830
|
const manualCloseRef = useRef(false);
|
|
828
831
|
const manualOpenRef = useRef(false);
|
|
829
832
|
const skipCloseReconnectRef = useRef(false);
|
|
@@ -912,17 +915,28 @@ var useWebSocket = (options) => {
|
|
|
912
915
|
stateRef.current = resolved;
|
|
913
916
|
setState(resolved);
|
|
914
917
|
};
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
if (socket2 === null) {
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
socketRef.current = null;
|
|
921
|
-
socketKeyRef.current = null;
|
|
922
|
-
if (isSocketActive(socket2)) {
|
|
923
|
-
socket2.close(code, reason);
|
|
924
|
-
}
|
|
918
|
+
const isActiveSocketEvent = useEffectEvent((socketEpoch) => {
|
|
919
|
+
return activeSocketEpochRef.current === socketEpoch;
|
|
925
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
|
+
);
|
|
926
940
|
const applyHeartbeatAction = useEffectEvent(
|
|
927
941
|
(action, error, reconnectTrigger) => {
|
|
928
942
|
heartbeat.stop();
|
|
@@ -957,7 +971,7 @@ var useWebSocket = (options) => {
|
|
|
957
971
|
};
|
|
958
972
|
skipCloseReconnectRef.current = true;
|
|
959
973
|
suppressReconnectRef.current = true;
|
|
960
|
-
closeSocket();
|
|
974
|
+
closeSocket({ trackClose: true });
|
|
961
975
|
}
|
|
962
976
|
);
|
|
963
977
|
const parseMessage = useEffectEvent((event) => {
|
|
@@ -1011,10 +1025,17 @@ var useWebSocket = (options) => {
|
|
|
1011
1025
|
lastError: parseError,
|
|
1012
1026
|
status: "error"
|
|
1013
1027
|
}));
|
|
1014
|
-
closeSocket(
|
|
1028
|
+
closeSocket({
|
|
1029
|
+
code: 1003,
|
|
1030
|
+
reason: "parse-error",
|
|
1031
|
+
trackClose: true
|
|
1032
|
+
});
|
|
1015
1033
|
}
|
|
1016
1034
|
});
|
|
1017
|
-
const handleError = useEffectEvent((event) => {
|
|
1035
|
+
const handleError = useEffectEvent((event, socketEpoch) => {
|
|
1036
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1018
1039
|
heartbeat.stop();
|
|
1019
1040
|
commitState((current) => ({
|
|
1020
1041
|
...current,
|
|
@@ -1024,9 +1045,18 @@ var useWebSocket = (options) => {
|
|
|
1024
1045
|
}));
|
|
1025
1046
|
options.onError?.(event);
|
|
1026
1047
|
});
|
|
1027
|
-
const handleClose = useEffectEvent((event) => {
|
|
1028
|
-
|
|
1029
|
-
|
|
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
|
+
}
|
|
1030
1060
|
heartbeat.stop();
|
|
1031
1061
|
updateBufferedAmount();
|
|
1032
1062
|
const pendingCloseAction = pendingCloseActionRef.current;
|
|
@@ -1106,7 +1136,11 @@ var useWebSocket = (options) => {
|
|
|
1106
1136
|
lastChangedAt: Date.now(),
|
|
1107
1137
|
status: "closing"
|
|
1108
1138
|
}));
|
|
1109
|
-
closeSocket(
|
|
1139
|
+
closeSocket({
|
|
1140
|
+
code,
|
|
1141
|
+
reason,
|
|
1142
|
+
trackClose: true
|
|
1143
|
+
});
|
|
1110
1144
|
};
|
|
1111
1145
|
const send = (message) => {
|
|
1112
1146
|
const socket2 = socketRef.current;
|
|
@@ -1158,8 +1192,12 @@ var useWebSocket = (options) => {
|
|
|
1158
1192
|
return;
|
|
1159
1193
|
}
|
|
1160
1194
|
const socket2 = new WebSocket(resolvedUrl, options.protocols);
|
|
1195
|
+
const socketEpoch = nextSocketEpochRef.current + 1;
|
|
1161
1196
|
socketRef.current = socket2;
|
|
1162
1197
|
socketKeyRef.current = nextSocketKey;
|
|
1198
|
+
activeSocketEpochRef.current = socketEpoch;
|
|
1199
|
+
closingSocketEpochRef.current = null;
|
|
1200
|
+
nextSocketEpochRef.current = socketEpoch;
|
|
1163
1201
|
socket2.binaryType = options.binaryType ?? "blob";
|
|
1164
1202
|
commitState((current) => ({
|
|
1165
1203
|
...current,
|
|
@@ -1168,16 +1206,22 @@ var useWebSocket = (options) => {
|
|
|
1168
1206
|
status: reconnect.status === "running" || reconnect.status === "scheduled" ? "reconnecting" : "connecting"
|
|
1169
1207
|
}));
|
|
1170
1208
|
const handleSocketOpen = (event) => {
|
|
1209
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1171
1212
|
handleOpen(event, socket2);
|
|
1172
1213
|
};
|
|
1173
1214
|
const handleSocketMessage = (event) => {
|
|
1215
|
+
if (!isActiveSocketEvent(socketEpoch)) {
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1174
1218
|
handleMessage(event);
|
|
1175
1219
|
};
|
|
1176
1220
|
const handleSocketError = (event) => {
|
|
1177
|
-
handleError(event);
|
|
1221
|
+
handleError(event, socketEpoch);
|
|
1178
1222
|
};
|
|
1179
1223
|
const handleSocketClose = (event) => {
|
|
1180
|
-
handleClose(event);
|
|
1224
|
+
handleClose(event, socketEpoch);
|
|
1181
1225
|
};
|
|
1182
1226
|
socket2.addEventListener("open", handleSocketOpen);
|
|
1183
1227
|
socket2.addEventListener("message", handleSocketMessage);
|
|
@@ -1201,6 +1245,8 @@ var useWebSocket = (options) => {
|
|
|
1201
1245
|
useEffect(() => () => {
|
|
1202
1246
|
suppressReconnectRef.current = true;
|
|
1203
1247
|
socketKeyRef.current = null;
|
|
1248
|
+
activeSocketEpochRef.current = null;
|
|
1249
|
+
closingSocketEpochRef.current = null;
|
|
1204
1250
|
terminalErrorRef.current = null;
|
|
1205
1251
|
const socket2 = socketRef.current;
|
|
1206
1252
|
socketRef.current = null;
|