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

refactor PageAccessoriesModal loadable dynamically

Yuki Takei 5 месяцев назад
Родитель
Сommit
1eeadd4884

+ 25 - 18
apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx

@@ -1,5 +1,5 @@
 import React, {
 import React, {
-  useMemo, useState, useCallback, type JSX,
+  useMemo, useCallback, useState, type JSX,
 } from 'react';
 } from 'react';
 
 
 import { useAtomValue } from 'jotai';
 import { useAtomValue } from 'jotai';
@@ -27,11 +27,14 @@ const PageAttachment = dynamic(() => import('./PageAttachment'), { ssr: false })
 const PageHistory = dynamic(() => import('./PageHistory').then(mod => mod.PageHistory), { ssr: false });
 const PageHistory = dynamic(() => import('./PageHistory').then(mod => mod.PageHistory), { ssr: false });
 const ShareLink = dynamic(() => import('./ShareLink').then(mod => mod.ShareLink), { ssr: false });
 const ShareLink = dynamic(() => import('./ShareLink').then(mod => mod.ShareLink), { ssr: false });
 
 
-const PageAccessoriesModalSubstance = (): JSX.Element => {
+interface PageAccessoriesModalSubstanceProps {
+  isWindowExpanded: boolean;
+  setIsWindowExpanded: (expanded: boolean) => void;
+}
 
 
-  const { t } = useTranslation();
+const PageAccessoriesModalSubstance = ({ isWindowExpanded, setIsWindowExpanded }: PageAccessoriesModalSubstanceProps): JSX.Element => {
 
 
-  const [isWindowExpanded, setIsWindowExpanded] = useState(false);
+  const { t } = useTranslation();
 
 
   const isSharedUser = useIsSharedUser();
   const isSharedUser = useIsSharedUser();
   const isGuestUser = useIsGuestUser();
   const isGuestUser = useIsGuestUser();
@@ -74,8 +77,8 @@ const PageAccessoriesModalSubstance = (): JSX.Element => {
   }, [t, close, isGuestUser, isReadOnlyUser, isSharedUser, isLinkSharingDisabled]);
   }, [t, close, isGuestUser, isReadOnlyUser, isSharedUser, isLinkSharingDisabled]);
 
 
   // Memoize expand/contract handlers
   // Memoize expand/contract handlers
-  const expandWindow = useCallback(() => setIsWindowExpanded(true), []);
-  const contractWindow = useCallback(() => setIsWindowExpanded(false), []);
+  const expandWindow = useCallback(() => setIsWindowExpanded(true), [setIsWindowExpanded]);
+  const contractWindow = useCallback(() => setIsWindowExpanded(false), [setIsWindowExpanded]);
 
 
   const buttons = useMemo(() => (
   const buttons = useMemo(() => (
     <span className="me-3">
     <span className="me-3">
@@ -92,16 +95,8 @@ const PageAccessoriesModalSubstance = (): JSX.Element => {
     return <></>;
     return <></>;
   }
   }
 
 
-  const { isOpened } = status;
-
   return (
   return (
-    <Modal
-      size="xl"
-      isOpen={isOpened}
-      toggle={close}
-      data-testid="page-accessories-modal"
-      className={`grw-page-accessories-modal ${styles['grw-page-accessories-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `}
-    >
+    <>
       <ModalHeader className={isDeviceLargerThanLg ? 'p-0' : ''} toggle={close} close={buttons}>
       <ModalHeader className={isDeviceLargerThanLg ? 'p-0' : ''} toggle={close} close={buttons}>
         {isDeviceLargerThanLg && (
         {isDeviceLargerThanLg && (
           <CustomNavTab
           <CustomNavTab
@@ -127,16 +122,28 @@ const PageAccessoriesModalSubstance = (): JSX.Element => {
           additionalClassNames={!isDeviceLargerThanLg ? ['grw-tab-content-style-md-down'] : undefined}
           additionalClassNames={!isDeviceLargerThanLg ? ['grw-tab-content-style-md-down'] : undefined}
         />
         />
       </ModalBody>
       </ModalBody>
-    </Modal>
+    </>
   );
   );
 };
 };
 
 
 export const PageAccessoriesModal = (): JSX.Element => {
 export const PageAccessoriesModal = (): JSX.Element => {
   const status = usePageAccessoriesModalStatus();
   const status = usePageAccessoriesModalStatus();
+  const { close } = usePageAccessoriesModalActions();
+  const [isWindowExpanded, setIsWindowExpanded] = useState(false);
 
 
-  if (status == null || !status.isOpened) {
+  if (status == null) {
     return <></>;
     return <></>;
   }
   }
 
 
-  return <PageAccessoriesModalSubstance />;
+  return (
+    <Modal
+      size="xl"
+      isOpen={status.isOpened}
+      toggle={close}
+      data-testid="page-accessories-modal"
+      className={`grw-page-accessories-modal ${styles['grw-page-accessories-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `}
+    >
+      {status.isOpened && <PageAccessoriesModalSubstance isWindowExpanded={isWindowExpanded} setIsWindowExpanded={setIsWindowExpanded} />}
+    </Modal>
+  );
 };
 };

+ 19 - 0
apps/app/src/client/components/PageAccessoriesModal/dynamic.tsx

@@ -0,0 +1,19 @@
+import type { JSX } from 'react';
+
+import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { usePageAccessoriesModalStatus } from '~/states/ui/modal/page-accessories';
+
+type PageAccessoriesModalProps = Record<string, unknown>;
+
+export const PageAccessoriesModalDynamic = (): JSX.Element => {
+  const status = usePageAccessoriesModalStatus();
+
+  const PageAccessoriesModal = useLazyLoader<PageAccessoriesModalProps>(
+    'page-accessories-modal',
+    () => import('./PageAccessoriesModal').then(mod => ({ default: mod.PageAccessoriesModal })),
+    status?.isOpened ?? false,
+  );
+
+  // PageAccessoriesModal handles early return and fadeout transition internally
+  return PageAccessoriesModal ? <PageAccessoriesModal /> : <></>;
+};

+ 1 - 1
apps/app/src/client/components/PageAccessoriesModal/index.ts

@@ -1 +1 @@
-export * from './PageAccessoriesModal';
+export { PageAccessoriesModalDynamic } from './dynamic';

+ 4 - 2
apps/app/src/components/Layout/BasicLayout.tsx

@@ -3,6 +3,9 @@ import React from 'react';
 
 
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
+// eslint-disable-next-line no-restricted-imports
+import { PageAccessoriesModalDynamic } from '~/client/components/PageAccessoriesModal';
+
 import { RawLayout } from './RawLayout';
 import { RawLayout } from './RawLayout';
 
 
 
 
@@ -34,7 +37,6 @@ const PageDuplicateModal = dynamic(() => import('~/client/components/PageDuplica
 const PageDeleteModal = dynamic(() => import('~/client/components/PageDeleteModal'), { ssr: false });
 const PageDeleteModal = dynamic(() => import('~/client/components/PageDeleteModal'), { ssr: false });
 const PageRenameModal = dynamic(() => import('~/client/components/PageRenameModal'), { ssr: false });
 const PageRenameModal = dynamic(() => import('~/client/components/PageRenameModal'), { ssr: false });
 const PagePresentationModal = dynamic(() => import('~/client/components/PagePresentationModal'), { ssr: false });
 const PagePresentationModal = dynamic(() => import('~/client/components/PagePresentationModal'), { ssr: false });
-const PageAccessoriesModal = dynamic(() => import('~/client/components/PageAccessoriesModal').then(mod => mod.PageAccessoriesModal), { ssr: false });
 const GrantedGroupsInheritanceSelectModal = dynamic(() => import('~/client/components/GrantedGroupsInheritanceSelectModal'), { ssr: false });
 const GrantedGroupsInheritanceSelectModal = dynamic(() => import('~/client/components/GrantedGroupsInheritanceSelectModal'), { ssr: false });
 const DeleteBookmarkFolderModal = dynamic(
 const DeleteBookmarkFolderModal = dynamic(
   () => import('~/client/components/DeleteBookmarkFolderModal').then(mod => mod.DeleteBookmarkFolderModal), { ssr: false },
   () => import('~/client/components/DeleteBookmarkFolderModal').then(mod => mod.DeleteBookmarkFolderModal), { ssr: false },
@@ -77,7 +79,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => {
       <PageDuplicateModal />
       <PageDuplicateModal />
       <PageDeleteModal />
       <PageDeleteModal />
       <PageRenameModal />
       <PageRenameModal />
-      <PageAccessoriesModal />
+      <PageAccessoriesModalDynamic />
       <DeleteAttachmentModal />
       <DeleteAttachmentModal />
       <DeleteBookmarkFolderModal />
       <DeleteBookmarkFolderModal />
       <PutbackPageModal />
       <PutbackPageModal />