Răsfoiți Sursa

omit SocketIoContainer

Yuki Takei 3 ani în urmă
părinte
comite
74935fa53e

+ 0 - 50
packages/app/src/client/services/SocketIoContainer.js

@@ -1,50 +0,0 @@
-import { Container } from 'unstated';
-
-import io from 'socket.io-client';
-
-import loggerFactory from '~/utils/logger';
-
-const logger = loggerFactory('growi:cli:SocketIoContainer');
-
-/**
- * Service container related to options for WebSocket
- * @extends {Container} unstated Container
- */
-export default class SocketIoContainer extends Container {
-
-  constructor(appContainer, namespace) {
-    super();
-
-    this.appContainer = appContainer;
-    this.appContainer.registerContainer(this);
-
-    const ns = namespace || '/';
-
-    this.socket = io(ns, {
-      transports: ['websocket'],
-    });
-
-    this.socket.on('connect_error', (error) => {
-      logger.error(error);
-    });
-    this.socket.on('error', (error) => {
-      logger.error(error);
-    });
-
-    this.state = {
-    };
-
-  }
-
-  /**
-   * Workaround for the mangling in production build to break constructor.name
-   */
-  static getClassName() {
-    return 'SocketIoContainer';
-  }
-
-  getSocket() {
-    return this.socket;
-  }
-
-}

+ 15 - 23
packages/app/src/components/InAppNotification/InAppNotificationDropdown.tsx

@@ -7,39 +7,29 @@ import {
   Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
 
-import SocketIoContainer from '~/client/services/SocketIoContainer';
 import { toastError } from '~/client/util/apiNotification';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { useSWRxInAppNotifications, useSWRxInAppNotificationStatus } from '~/stores/in-app-notification';
+import { useDefaultSocket } from '~/stores/socket-io';
 import loggerFactory from '~/utils/logger';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-
 import InAppNotificationList from './InAppNotificationList';
 
 
 const logger = loggerFactory('growi:InAppNotificationDropdown');
 
-type Props = {
-  socketIoContainer: SocketIoContainer,
-};
 
-const InAppNotificationDropdown: FC<Props> = (props: Props) => {
+export const InAppNotificationDropdown = (): JSX.Element => {
   const { t } = useTranslation();
 
   const [isOpen, setIsOpen] = useState(false);
   const limit = 6;
+
+  const { data: socket } = useDefaultSocket();
   const { data: inAppNotificationData, mutate: mutateInAppNotificationData } = useSWRxInAppNotifications(limit);
   const { data: inAppNotificationUnreadStatusCount, mutate: mutateInAppNotificationUnreadStatusCount } = useSWRxInAppNotificationStatus();
 
 
-  const initializeSocket = useCallback((props) => {
-    const socket = props.socketIoContainer.getSocket();
-    socket.on('notificationUpdated', () => {
-      mutateInAppNotificationUnreadStatusCount();
-    });
-  }, [mutateInAppNotificationUnreadStatusCount]);
-
   const updateNotificationStatus = async() => {
     try {
       await apiv3Post('/in-app-notification/read');
@@ -51,8 +41,17 @@ const InAppNotificationDropdown: FC<Props> = (props: Props) => {
   };
 
   useEffect(() => {
-    initializeSocket(props);
-  }, [initializeSocket, props]);
+    if (socket != null) {
+      socket.on('notificationUpdated', () => {
+        mutateInAppNotificationUnreadStatusCount();
+      });
+
+      // clean up
+      return () => {
+        socket.off('notificationUpdated');
+      };
+    }
+  }, [mutateInAppNotificationUnreadStatusCount, socket]);
 
 
   const toggleDropdownHandler = async() => {
@@ -96,10 +95,3 @@ const InAppNotificationDropdown: FC<Props> = (props: Props) => {
     </Dropdown>
   );
 };
-
-/**
- * Wrapper component for using unstated
- */
-const InAppNotificationDropdownWrapper = withUnstatedContainers(InAppNotificationDropdown, [SocketIoContainer]);
-
-export default InAppNotificationDropdownWrapper;

+ 41 - 0
packages/app/src/stores/socket-io.ts

@@ -0,0 +1,41 @@
+import io, { Socket } from 'socket.io-client';
+import { SWRResponse } from 'swr';
+import useSWRImmutable from 'swr/immutable';
+
+import loggerFactory from '~/utils/logger';
+
+const logger = loggerFactory('growi:cli:stores:socket-io');
+
+
+const socketFactory = (namespace: string): Socket => {
+  const socket = io(namespace, {
+    transports: ['websocket'],
+  });
+
+  socket.on('connect_error', (error) => {
+    logger.error(namespace, error);
+  });
+  socket.on('error', (error) => {
+    logger.error(namespace, error);
+  });
+
+  return socket;
+};
+
+const useSocket = (namespace: string): SWRResponse<Socket, Error> => {
+  const swrResponse = useSWRImmutable(namespace, null);
+
+  if (swrResponse.data === undefined) {
+    swrResponse.mutate(socketFactory(namespace));
+  }
+
+  return swrResponse;
+};
+
+export const useDefaultSocket = (): SWRResponse<Socket, Error> => {
+  return useSocket('/');
+};
+
+export const useAdminSocket = (): SWRResponse<Socket, Error> => {
+  return useSocket('/admin');
+};