Просмотр исходного кода

Merge pull request #4663 from weseek/fix/80942-hit-api-multi-times-when-page-scrolled

Fix/80942 hit api multi times when page scrolled
cao 4 лет назад
Родитель
Сommit
18b042fe29

+ 2 - 2
packages/app/src/components/Navbar/SubNavButtons.jsx

@@ -10,7 +10,7 @@ import LikeButtons from '../LikeButtons';
 import SubscribeButton from '../SubscribeButton';
 import PageManagement from '../Page/PageManagement';
 
-const SubnavButtons = (props) => {
+const SubnavButtons = React.memo((props) => {
   const {
     appContainer, navigationContainer, pageContainer, isCompactMode,
   } = props;
@@ -49,7 +49,7 @@ const SubnavButtons = (props) => {
       )}
     </>
   );
-};
+});
 
 /**
  * Wrapper component for using unstated

+ 24 - 35
packages/app/src/components/SubscribeButton.tsx

@@ -1,10 +1,12 @@
-import React, {
-  FC, useState, useCallback, useEffect,
-} from 'react';
+import React, { FC } from 'react';
 
+
+import { Types } from 'mongoose';
 import { useTranslation } from 'react-i18next';
 import { UncontrolledTooltip } from 'reactstrap';
 import { withUnstatedContainers } from './UnstatedUtils';
+import { useSWRxSubscribeButton } from '../stores/page';
+
 
 import { toastError } from '~/client/util/apiNotification';
 import AppContainer from '~/client/services/AppContainer';
@@ -12,17 +14,29 @@ import PageContainer from '~/client/services/PageContainer';
 
 type Props = {
   appContainer: AppContainer,
-  pageId: string,
+  pageId: Types.ObjectId,
 };
 
 const SubscribeButton: FC<Props> = (props: Props) => {
   const { t } = useTranslation();
-
   const { appContainer, pageId } = props;
-  const [isSubscribing, setIsSubscribing] = useState<boolean | null>(null);
+  const { data: subscriptionData, mutate } = useSWRxSubscribeButton(pageId);
+
+  let isSubscribed;
+
+  switch (subscriptionData?.status) {
+    case true:
+      isSubscribed = true;
+      break;
+    case false:
+      isSubscribed = false;
+      break;
+    default:
+      isSubscribed = null;
+  }
 
-  const buttonClass = `${isSubscribing ? 'active' : ''} ${appContainer.isGuestUser ? 'disabled' : ''}`;
-  const iconClass = isSubscribing || isSubscribing == null ? 'fa fa-eye' : 'fa fa-eye-slash';
+  const buttonClass = `${isSubscribed ? 'active' : ''} ${appContainer.isGuestUser ? 'disabled' : ''}`;
+  const iconClass = isSubscribed || isSubscribed == null ? 'fa fa-eye' : 'fa fa-eye-slash';
 
   const handleClick = async() => {
     if (appContainer.isGuestUser) {
@@ -30,10 +44,9 @@ const SubscribeButton: FC<Props> = (props: Props) => {
     }
 
     try {
-      const res = await appContainer.apiv3Put('page/subscribe', { pageId, status: !isSubscribing });
+      const res = await appContainer.apiv3Put('page/subscribe', { pageId, status: !isSubscribed });
       if (res) {
-        const { subscription } = res.data;
-        setIsSubscribing(subscription.status === 'SUBSCRIBE');
+        mutate();
       }
     }
     catch (err) {
@@ -41,30 +54,6 @@ const SubscribeButton: FC<Props> = (props: Props) => {
     }
   };
 
-  const fetchSubscriptionStatus = useCallback(async() => {
-    if (appContainer.isGuestUser) {
-      return;
-    }
-
-    try {
-      const res = await appContainer.apiv3Get('page/subscribe', { pageId });
-      const { subscribing } = res.data;
-      if (subscribing == null) {
-        setIsSubscribing(null);
-      }
-      else {
-        setIsSubscribing(subscribing);
-      }
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }, [appContainer, pageId]);
-
-  useEffect(() => {
-    fetchSubscriptionStatus();
-  }, [fetchSubscriptionStatus]);
-
   return (
     <>
       <button

+ 1 - 0
packages/app/src/interfaces/in-app-notification-settings.ts

@@ -7,6 +7,7 @@ export enum subscribeRuleNames {
 export enum SubscribeRuleDescriptions {
   PAGE_CREATE = 'in_app_notification_settings.default_subscribe_rules.page_create',
 }
+
 export interface ISubscribeRule {
   name: subscribeRuleNames;
   isEnabled: boolean;

+ 16 - 0
packages/app/src/stores/page.tsx

@@ -1,5 +1,6 @@
 import useSWR, { SWRResponse } from 'swr';
 
+import { Types } from 'mongoose';
 import { apiv3Get } from '~/client/util/apiv3-client';
 
 import { IPage } from '~/interfaces/page';
@@ -31,3 +32,18 @@ export const useSWRxPageList = (
     }),
   );
 };
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export const useSWRxSubscribeButton = <Data, Error>(
+  pageId: Types.ObjectId,
+
+): SWRResponse<{status: boolean | null}, Error> => {
+  return useSWR(
+    ['/page/subscribe', pageId],
+    (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then((response) => {
+      return {
+        status: response.data.subscribing,
+      };
+    }),
+  );
+};