Re-enable StrictMode by handling WebSocket reconnection

GitLab: #150
GitLab: #170
Change-Id: Ibf20b8b20773c106f5fdc2bbed04d06e6bc97bcf
diff --git a/client/src/contexts/WebSocketProvider.tsx b/client/src/contexts/WebSocketProvider.tsx
index 8c530c6..0d153dc 100644
--- a/client/src/contexts/WebSocketProvider.tsx
+++ b/client/src/contexts/WebSocketProvider.tsx
@@ -54,6 +54,7 @@
   const [isConnected, setIsConnected] = useState(false);
   const webSocketRef = useRef<WebSocket>();
   const callbacksRef = useRef<WebSocketCallbacks>(buildWebSocketCallbacks());
+  const reconnectionTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
 
   const { token: accessToken } = useAuthContext();
 
@@ -83,20 +84,24 @@
 
     const webSocket = new WebSocket(url);
 
-    webSocket.onopen = () => {
-      console.debug('WebSocket connected');
-      setIsConnected(true);
-    };
-
-    webSocket.onclose = () => {
+    const close = (reconnect = false) => {
       console.debug('WebSocket disconnected');
       setIsConnected(false);
       for (const callbacks of Object.values(callbacksRef.current)) {
         callbacks.clear();
       }
-      setTimeout(connect, 1000);
+      if (reconnect) {
+        reconnectionTimeoutRef.current = setTimeout(connect, 2000);
+      }
     };
 
+    webSocket.onopen = () => {
+      console.debug('WebSocket connected');
+      setIsConnected(true);
+    };
+
+    webSocket.onclose = () => close(true);
+
     webSocket.onmessage = <T extends WebSocketMessageType>(event: MessageEvent<string>) => {
       const messageString = event.data;
       console.debug('WebSocket received message', messageString);
@@ -119,13 +124,21 @@
     };
 
     webSocket.onerror = (event: Event) => {
-      console.error('Closing WebSocket due to an error:', event);
-      webSocketRef.current?.close();
+      console.error('WebSocket errored', event);
     };
 
     webSocketRef.current = webSocket;
 
     return () => {
+      // Cancel any previous reconnection attempt
+      if (reconnectionTimeoutRef.current !== undefined) {
+        clearTimeout(reconnectionTimeoutRef.current);
+        reconnectionTimeoutRef.current = undefined;
+      }
+
+      // Setup a closure without reconnection
+      webSocket.onclose = () => close();
+
       switch (webSocket.readyState) {
         case webSocket.CONNECTING:
           webSocket.onopen = () => webSocket.close();