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.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 closeSocket = useEffectEvent((code, reason) => {
916
- const socket2 = socketRef.current;
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(1003, "parse-error");
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
- socketRef.current = null;
1029
- socketKeyRef.current = null;
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(code, reason);
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;