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

Use SWR for current user bookmarks

https://youtrack.weseek.co.jp/issue/GW-7839
- Add SWR method for bookmarks item
- Set page as optional parameter in useSWRCurrentUserBookmarks
- Implement SWR to get pages data in Bookmark component
- Remove refreshBookmarkList props from Bookmark component
- Call mutateCurrentUserBookmark from PageListItemL and SubNavButtons
Mudana-Grune 3 лет назад
Родитель
Сommit
3a4996c4b3

+ 4 - 2
packages/app/src/components/Navbar/SubNavButtons.tsx

@@ -7,7 +7,7 @@ import {
 import { useIsGuestUser } from '~/stores/context';
 import { IPageForPageDuplicateModal } from '~/stores/modal';
 
-import { useSWRBookmarkInfo } from '../../stores/bookmark';
+import { useSWRBookmarkInfo, useSWRCurrentUserBookmarks } from '../../stores/bookmark';
 import { useSWRxPageInfo } from '../../stores/page';
 import { useSWRxUsersList } from '../../stores/user';
 import BookmarkButtons from '../BookmarkButtons';
@@ -51,6 +51,7 @@ const SubNavButtonsSubstance = (props: SubNavButtonsSubstanceProps): JSX.Element
   const { mutate: mutatePageInfo } = useSWRxPageInfo(pageId, shareLinkId);
 
   const { data: bookmarkInfo, mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(pageId);
+  const { mutate: mutateCurrentUserBookmark } = useSWRCurrentUserBookmarks();
 
   const likerIds = isIPageInfoForEntity(pageInfo) ? (pageInfo.likerIds ?? []).slice(0, 15) : [];
   const seenUserIds = isIPageInfoForEntity(pageInfo) ? (pageInfo.seenUserIds ?? []).slice(0, 15) : [];
@@ -95,7 +96,8 @@ const SubNavButtonsSubstance = (props: SubNavButtonsSubstanceProps): JSX.Element
     await toggleBookmark(pageId, pageInfo.isBookmarked);
     mutatePageInfo();
     mutateBookmarkInfo();
-  }, [isGuestUser, mutateBookmarkInfo, mutatePageInfo, pageId, pageInfo]);
+    mutateCurrentUserBookmark();
+  }, [isGuestUser, mutateBookmarkInfo, mutatePageInfo, mutateCurrentUserBookmark, pageId, pageInfo]);
 
   const duplicateMenuItemClickHandler = useCallback(async(_pageId: string): Promise<void> => {
     if (onClickDuplicateMenuItem == null || path == null) {

+ 3 - 1
packages/app/src/components/PageList/PageListItemL.tsx

@@ -23,6 +23,7 @@ import {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
 } from '~/interfaces/ui';
 import LinkedPagePath from '~/models/linked-page-path';
+import { useSWRCurrentUserBookmarks } from '~/stores/bookmark';
 import {
   usePageRenameModal, usePageDuplicateModal, usePageDeleteModal, usePutBackPageModal,
 } from '~/stores/modal';
@@ -85,7 +86,7 @@ const PageListItemLSubstance: ForwardRefRenderFunction<ISelectable, Props> = (pr
 
   const shouldFetch = isSelected && (pageData != null || pageMeta != null);
   const { data: pageInfo } = useSWRxPageInfo(shouldFetch ? pageData?._id : null);
-
+  const { mutate: mutateCurrentUserBookmark } = useSWRCurrentUserBookmarks();
   const elasticSearchResult = isIPageSearchMeta(pageMeta) ? pageMeta.elasticSearchResult : null;
   const revisionShortBody = isIPageInfoForListing(pageMeta) ? pageMeta.revisionShortBody : null;
 
@@ -122,6 +123,7 @@ const PageListItemLSubstance: ForwardRefRenderFunction<ISelectable, Props> = (pr
   const bookmarkMenuItemClickHandler = async(_pageId: string, _newValue: boolean): Promise<void> => {
     const bookmarkOperation = _newValue ? bookmark : unbookmark;
     await bookmarkOperation(_pageId);
+    mutateCurrentUserBookmark();
   };
 
   const duplicateMenuItemClickHandler = useCallback(() => {

+ 8 - 35
packages/app/src/components/Sidebar/Bookmarks.tsx

@@ -1,30 +1,25 @@
 
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useEffect } from 'react';
 
 import { DevidedPagePath } from '@growi/core';
 import { useTranslation } from 'react-i18next';
 import { UncontrolledTooltip, DropdownToggle } from 'reactstrap';
 
 import { unbookmark } from '~/client/services/page-operation';
-import { toastError } from '~/client/util/apiNotification';
-import { apiv3Get } from '~/client/util/apiv3-client';
 import { IPageHasId } from '~/interfaces/page';
-import { useCurrentUser, useIsGuestUser } from '~/stores/context';
-import loggerFactory from '~/utils/logger';
+import { useSWRCurrentUserBookmarks } from '~/stores/bookmark';
+import { useIsGuestUser } from '~/stores/context';
 
 import { MenuItemType, PageItemControl } from '../Common/Dropdown/PageItemControl';
 
-const logger = loggerFactory('growi:BookmarkList');
-// TODO: Remove pagination and apply  scrolling (not infinity)
-const ACTIVE_PAGE = 1;
 
 type Props = {
   pages: IPageHasId[] | undefined,
-  refreshBookmarkList: () => void
 }
 
 const BookmarksItem = (props: Props) => {
-  const { pages, refreshBookmarkList } = props;
+  const { pages } = props;
+  const { mutate: mutateCurrentUserBookmark } = useSWRCurrentUserBookmarks();
 
   const generateBookmarkedPageList = pages?.map((page) => {
     const dPagePath = new DevidedPagePath(page.path, false, true);
@@ -33,7 +28,7 @@ const BookmarksItem = (props: Props) => {
 
     const bookmarkMenuItemClickHandler = (async() => {
       await unbookmark(page._id);
-      refreshBookmarkList();
+      mutateCurrentUserBookmark();
     });
 
 
@@ -81,30 +76,8 @@ const BookmarksItem = (props: Props) => {
 
 const Bookmarks = () : JSX.Element => {
   const { t } = useTranslation();
-  const { data: currentUser } = useCurrentUser();
   const { data: isGuestUser } = useIsGuestUser();
-  const [pages, setPages] = useState<IPageHasId[]>([]);
-  const page = ACTIVE_PAGE;
-
-  const getMyBookmarkList = useCallback(async() => {
-    try {
-      const res = await apiv3Get(`/bookmarks/${currentUser?._id}`, { page });
-      const { paginationResult } = res.data;
-      setPages(paginationResult.docs.map((page) => {
-        return {
-          ...page.page,
-        };
-      }));
-    }
-    catch (error) {
-      logger.error('failed to fetch data', error);
-      toastError(error, 'Error occurred in bookmark page list');
-    }
-  }, [currentUser, page]);
-
-  useEffect(() => {
-    getMyBookmarkList();
-  }, [getMyBookmarkList]);
+  const { data: pages } = useSWRCurrentUserBookmarks();
 
   const renderBookmarksItem = () => {
     if (pages?.length === 0) {
@@ -114,7 +87,7 @@ const Bookmarks = () : JSX.Element => {
         </h3>
       );
     }
-    return <BookmarksItem pages={pages} refreshBookmarkList={getMyBookmarkList} />;
+    return <BookmarksItem pages={pages} />;
   };
 
   return (

+ 19 - 0
packages/app/src/stores/bookmark.ts

@@ -1,9 +1,12 @@
 import { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
+import { IPageHasId } from '~/interfaces/page';
+
 import { apiv3Get } from '../client/util/apiv3-client';
 import { IBookmarkInfo } from '../interfaces/bookmark-info';
 
+import { useCurrentUser } from './context';
 
 export const useSWRBookmarkInfo = (pageId: string | null | undefined): SWRResponse<IBookmarkInfo, Error> => {
   return useSWRImmutable(
@@ -17,3 +20,19 @@ export const useSWRBookmarkInfo = (pageId: string | null | undefined): SWRRespon
     }),
   );
 };
+
+export const useSWRCurrentUserBookmarks = (page?: number| null| undefined): SWRResponse<IPageHasId[], Error> => {
+  const { data: currentUser } = useCurrentUser();
+  const currentPage = page ?? 1;
+  return useSWRImmutable(
+    currentUser != null ? `/bookmarks/${currentUser._id}` : null,
+    endpoint => apiv3Get(endpoint, { page: currentPage }).then((response) => {
+      const { paginationResult } = response.data;
+      return paginationResult.docs.map((item) => {
+        return {
+          ...item.page,
+        };
+      });
+    }),
+  );
+};