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

add injectTo method to useSWRxPageInfoForList

Yuki Takei 4 лет назад
Родитель
Сommit
5954016ba9

+ 7 - 29
packages/app/src/components/DescendantsPageList.tsx

@@ -37,41 +37,19 @@ export const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element
   const { data: isGuestUser } = useIsGuestUser();
 
   const pageIds = pagingResult?.items?.map(page => page._id);
-  const { data: idToPageInfo } = useSWRxPageInfoForList(pageIds, true);
+  const { injectTo } = useSWRxPageInfoForList(pageIds, true);
 
-  let pagingResultWithMeta: IPagingResult<IPageWithMeta> | undefined;
+  let pageWithMetas: IPageWithMeta[] = [];
 
   // for mutation
   const { advance: advancePt } = usePageTreeTermManager();
 
   // initial data
   if (pagingResult != null) {
-    const pages = pagingResult.items;
-
     // convert without meta at first
-    pagingResultWithMeta = {
-      ...pagingResult,
-      items: pages.map(page => convertToIPageWithEmptyMeta(page)),
-    };
-  }
-
-  // inject data for listing
-  if (pagingResult != null) {
-    const pages = pagingResult.items;
-
-    const pageWithMetas = pages.map((page) => {
-      const pageInfo = (idToPageInfo ?? {})[page._id];
-
-      return {
-        pageData: page,
-        pageMeta: pageInfo,
-      } as IPageWithMeta;
-    });
-
-    pagingResultWithMeta = {
-      ...pagingResult,
-      items: pageWithMetas,
-    };
+    pageWithMetas = pagingResult.items.map(page => convertToIPageWithEmptyMeta(page));
+    // inject data for listing
+    pageWithMetas = injectTo(pageWithMetas);
   }
 
   const pageDeletedHandler: OnDeletedFunction = useCallback((...args) => {
@@ -88,7 +66,7 @@ export const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element
     setActivePage(selectedPageNumber);
   }
 
-  if (pagingResult == null || pagingResultWithMeta == null) {
+  if (pagingResult == null) {
     return (
       <div className="wiki">
         <div className="text-muted text-center">
@@ -103,7 +81,7 @@ export const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element
   return (
     <>
       <PageList
-        pages={pagingResultWithMeta}
+        pages={pageWithMetas}
         isEnableActions={!isGuestUser}
         onPagesDeleted={pageDeletedHandler}
       />

+ 6 - 10
packages/app/src/components/IdenticalPathPage.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
 
 import { DevidedPagePath } from '@growi/core';
 
-import { IPageHasId, IPageWithMeta } from '~/interfaces/page';
+import { IPageHasId } from '~/interfaces/page';
 import { useCurrentPagePath, useIsSharedUser } from '~/stores/context';
 import { useDescendantsPageListModal } from '~/stores/modal';
 import { useSWRxPageInfoForList } from '~/stores/page';
@@ -66,10 +66,12 @@ const IdenticalPathPage:FC<IdenticalPathPageProps> = (props: IdenticalPathPagePr
   const { data: currentPath } = useCurrentPagePath();
   const { data: isSharedUser } = useIsSharedUser();
 
-  const { data: idToPageInfoMap } = useSWRxPageInfoForList(pageIds, true);
+  const { injectTo } = useSWRxPageInfoForList(pageIds, true);
 
   const { open: openDescendantPageListModal } = useDescendantsPageListModal();
 
+  const injectedPages = injectTo(pages);
+
   return (
     <div className="d-flex flex-column flex-lg-row-reverse">
 
@@ -95,14 +97,8 @@ const IdenticalPathPage:FC<IdenticalPathPageProps> = (props: IdenticalPathPagePr
 
         <div className="page-list">
           <ul className="page-list-ul list-group list-group-flush">
-            {pages.map((page) => {
-              const pageId = page._id;
-              const pageInfo = (idToPageInfoMap ?? {})[pageId];
-
-              const pageWithMeta: IPageWithMeta = {
-                pageData: page,
-                pageMeta: pageInfo,
-              };
+            {injectedPages.map((pageWithMeta) => {
+              const pageId = pageWithMeta.pageData._id;
 
               return (
                 <PageListItemL

+ 2 - 3
packages/app/src/components/PageList/PageList.tsx

@@ -2,14 +2,13 @@ import React from 'react';
 import { useTranslation } from 'react-i18next';
 
 import { IPageWithMeta } from '~/interfaces/page';
-import { IPagingResult } from '~/interfaces/paging-result';
 import { OnDeletedFunction } from '~/interfaces/ui';
 
 import { PageListItemL } from './PageListItemL';
 
 
 type Props = {
-  pages: IPagingResult<IPageWithMeta>,
+  pages: IPageWithMeta[],
   isEnableActions?: boolean,
   onPagesDeleted?: OnDeletedFunction,
 }
@@ -28,7 +27,7 @@ const PageList = (props: Props): JSX.Element => {
     );
   }
 
-  const pageList = pages.items.map(page => (
+  const pageList = pages.map(page => (
     <PageListItemL
       key={page.pageData._id}
       page={page}

+ 5 - 0
packages/app/src/interfaces/page.ts

@@ -99,6 +99,11 @@ export type IPageWithMeta<M = IPageInfoAll> = {
   pageMeta?: M,
 };
 
+export type IPageWithAnyMeta = {
+  pageData: IPageHasId,
+  pageMeta?: unknown,
+};
+
 export type IPageToDeleteWithMeta<M = IPageInfoAll> = {
   pageData: Partial<IPage & HasObjectId & { path: string }>,
   pageMeta?: M,

+ 29 - 3
packages/app/src/stores/page.tsx

@@ -4,7 +4,7 @@ import useSWRImmutable from 'swr/immutable';
 import { apiv3Get } from '~/client/util/apiv3-client';
 
 import {
-  IPageInfo, IPageHasId, IPageInfoForOperation, IPageInfoForListing,
+  IPageInfo, IPageHasId, IPageInfoForOperation, IPageInfoForListing, IPageWithMeta, IPageWithAnyMeta,
 } from '~/interfaces/page';
 import { IPagingResult } from '~/interfaces/paging-result';
 import { apiGet } from '../client/util/apiv1-client';
@@ -91,15 +91,41 @@ export const useSWRxPageInfo = (
   );
 };
 
+type PageInfoInjector = {
+  injectTo: (pages: (IPageHasId | IPageWithAnyMeta)[]) => IPageWithMeta[],
+}
+
+const isIPageWithMeta = (page: IPageHasId | IPageWithAnyMeta): page is IPageWithAnyMeta => {
+  return 'pageData' in page;
+};
+
 export const useSWRxPageInfoForList = (
     pageIds: string[] | null | undefined,
     attachShortBody = false,
-): SWRResponse<Record<string, IPageInfo | IPageInfoForListing>, Error> => {
+): SWRResponse<Record<string, IPageInfo | IPageInfoForListing>, Error> & PageInfoInjector => {
 
   const shouldFetch = pageIds != null && pageIds.length > 0;
 
-  return useSWRImmutable(
+  const swrResult = useSWRImmutable<Record<string, IPageInfo | IPageInfoForListing>>(
     shouldFetch ? ['/page-listing/info', pageIds, attachShortBody] : null,
     (endpoint, pageIds, attachShortBody) => apiv3Get(endpoint, { pageIds, attachShortBody }).then(response => response.data),
   );
+
+  return {
+    ...swrResult,
+    injectTo: (pages: (IPageHasId | IPageWithAnyMeta)[]) => {
+      return pages.map((item) => {
+        const page: IPageHasId = isIPageWithMeta(item) ? item.pageData : item;
+        const orgPageMeta = isIPageWithMeta(item) ? item.pageMeta : undefined;
+
+        // get an applicable IPageInfo
+        const applicablePageInfo = (swrResult.data ?? {})[page._id];
+
+        return {
+          pageData: page,
+          pageMeta: applicablePageInfo ?? orgPageMeta,
+        };
+      });
+    },
+  };
 };