Procházet zdrojové kódy

refactor PageDuplicateModal

Yuki Takei před 6 měsíci
rodič
revize
8dd2ed2e36
1 změnil soubory, kde provedl 34 přidání a 13 odebrání
  1. 34 13
      apps/app/src/client/components/PageDuplicateModal.tsx

+ 34 - 13
apps/app/src/client/components/PageDuplicateModal.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useState, useEffect, useCallback, useMemo, type JSX,
+  useState, useEffect, useCallback, useMemo,
 } from 'react';
 
 import { useAtomValue } from 'jotai';
@@ -19,8 +19,10 @@ import DuplicatePathsTable from './DuplicatedPathsTable';
 import ApiErrorMessageList from './PageManagement/ApiErrorMessageList';
 import PagePathAutoComplete from './PagePathAutoComplete';
 
-
-const PageDuplicateModal = (): JSX.Element => {
+/**
+ * PageDuplicateModalSubstance - Heavy processing component (rendered only when modal is open)
+ */
+const PageDuplicateModalSubstance: React.FC = () => {
   const { t } = useTranslation();
 
   const siteUrl = useSiteUrl();
@@ -39,6 +41,12 @@ const PageDuplicateModal = (): JSX.Element => {
   const [isDuplicateRecursivelyWithoutExistPath, setIsDuplicateRecursivelyWithoutExistPath] = useState(true);
   const [onlyDuplicateUserRelatedResources, setOnlyDuplicateUserRelatedResources] = useState(false);
 
+  // Memoize computed values
+  const isTargetPageDuplicate = useMemo(() => existingPaths.includes(pageNameInput), [existingPaths, pageNameInput]);
+  const submitButtonEnabled = useMemo(() => (
+    existingPaths.length === 0 || (isDuplicateRecursively && isDuplicateRecursivelyWithoutExistPath)
+  ), [existingPaths.length, isDuplicateRecursively, isDuplicateRecursivelyWithoutExistPath]);
+
   const updateSubordinatedList = useCallback(async() => {
     if (page == null) {
       return;
@@ -90,14 +98,14 @@ const PageDuplicateModal = (): JSX.Element => {
    * change pageNameInput
    * @param {string} value
    */
-  function inputChangeHandler(value) {
+  const inputChangeHandler = useCallback((value) => {
     setErrs(null);
     setPageNameInput(value);
-  }
+  }, []);
 
-  function changeIsDuplicateRecursivelyHandler() {
+  const changeIsDuplicateRecursivelyHandler = useCallback(() => {
     setIsDuplicateRecursively(!isDuplicateRecursively);
-  }
+  }, [isDuplicateRecursively]);
 
   useEffect(() => {
     if (page != null && isOpened) {
@@ -156,7 +164,6 @@ const PageDuplicateModal = (): JSX.Element => {
     }
 
     const { path } = page;
-    const isTargetPageDuplicate = existingPaths.includes(pageNameInput);
 
     return (
       <>
@@ -257,9 +264,6 @@ const PageDuplicateModal = (): JSX.Element => {
       return <></>;
     }
 
-    const submitButtonEnabled = existingPaths.length === 0
-    || (isDuplicateRecursively && isDuplicateRecursivelyWithoutExistPath);
-
     return (
       <>
         <ApiErrorMessageList errs={errs} targetPath={pageNameInput} />
@@ -278,7 +282,7 @@ const PageDuplicateModal = (): JSX.Element => {
 
 
   return (
-    <Modal size="lg" isOpen={isOpened} toggle={closeDuplicateModal} data-testid="page-duplicate-modal" className="grw-duplicate-page" autoFocus={false}>
+    <>
       <ModalHeader tag="h4" toggle={closeDuplicateModal}>
         { t('modal_duplicate.label.Duplicate page') }
       </ModalHeader>
@@ -288,9 +292,26 @@ const PageDuplicateModal = (): JSX.Element => {
       <ModalFooter>
         {renderFooterContent()}
       </ModalFooter>
-    </Modal>
+    </>
   );
 };
 
+/**
+ * PageDuplicateModal - Container component (lightweight, always rendered)
+ */
+const PageDuplicateModal = (): React.JSX.Element => {
+  const { isOpened } = usePageDuplicateModalStatus();
+  const { close: closeDuplicateModal } = usePageDuplicateModalActions();
+
+  if (!isOpened) {
+    return <></>;
+  }
+
+  return (
+    <Modal size="lg" isOpen={isOpened} toggle={closeDuplicateModal} data-testid="page-duplicate-modal" className="grw-duplicate-page" autoFocus={false}>
+      <PageDuplicateModalSubstance />
+    </Modal>
+  );
+};
 
 export default PageDuplicateModal;