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

Improved useIsEnabledUnsavedWarning to get val from cache when using event

Taichi Masuyama 3 лет назад
Родитель
Сommit
9855548310

+ 11 - 12
packages/app/src/components/PageEditor.tsx

@@ -4,7 +4,7 @@ import React, {
 
 import EventEmitter from 'events';
 
-import { envUtils, PageGrant } from '@growi/core';
+import { envUtils, IPageHasId, PageGrant } from '@growi/core';
 import detectIndent from 'detect-indent';
 import { useTranslation } from 'next-i18next';
 import { useRouter } from 'next/router';
@@ -36,6 +36,7 @@ import loggerFactory from '~/utils/logger';
 import Editor from './PageEditor/Editor';
 import Preview from './PageEditor/Preview';
 import scrollSyncHelper from './PageEditor/ScrollSyncHelper';
+import { useSWRConfig } from 'swr';
 
 
 const logger = loggerFactory('growi:PageEditor');
@@ -115,7 +116,7 @@ const PageEditor = React.memo((): JSX.Element => {
   }, [setMarkdownWithDebounce]);
 
   // return true if the save succeeds, otherwise false.
-  const save = useCallback(async(opts?: {overwriteScopesOfDescendants: boolean}): Promise<boolean> => {
+  const save = useCallback(async(opts?: {overwriteScopesOfDescendants: boolean}): Promise<IPageHasId | null> => {
     if (grantData == null || isSlackEnabled == null || currentPathname == null) {
       logger.error('Some materials to save are invalid', { grantData, isSlackEnabled, currentPathname });
       throw new Error('Some materials to save are invalid');
@@ -136,14 +137,7 @@ const PageEditor = React.memo((): JSX.Element => {
         markdownToSave.current,
       );
 
-      // TODO: fix here
-      const _onbeforeunload = onbeforeunload;
-      onbeforeunload = null;
-      await router.push(`/${page._id}`);
-      onbeforeunload = _onbeforeunload;
-
-      mutateIsEnabledUnsavedWarning(false);
-      return true;
+      return page;
     }
     catch (error) {
       logger.error('failed to save', error);
@@ -156,7 +150,7 @@ const PageEditor = React.memo((): JSX.Element => {
         //   lastUpdateUser: error.data.user,
         // });
       }
-      return false;
+      return null;
     }
 
   // eslint-disable-next-line max-len
@@ -167,7 +161,12 @@ const PageEditor = React.memo((): JSX.Element => {
       return;
     }
 
-    await save(opts);
+    const page = await save(opts);
+    if (page == null) {
+      return;
+    }
+    await mutateIsEnabledUnsavedWarning(false);
+    await router.push(`/${page._id}`);
     mutateEditorMode(EditorMode.View);
   }, [editorMode, save, mutateEditorMode]);
 

+ 10 - 2
packages/app/src/components/PageEditorByHackmd.tsx

@@ -29,6 +29,7 @@ import {
 import loggerFactory from '~/utils/logger';
 
 import HackmdEditor from './PageEditorByHackmd/HackmdEditor';
+import { useRouter } from 'next/router';
 
 const logger = loggerFactory('growi:PageEditorByHackmd');
 
@@ -41,6 +42,8 @@ type HackEditorRef = {
 export const PageEditorByHackmd = (): JSX.Element => {
 
   const { t } = useTranslation();
+  const router = useRouter();
+
   const { data: editorMode, mutate: mutateEditorMode } = useEditorMode();
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPathname } = useCurrentPathname();
@@ -100,11 +103,16 @@ export const PageEditorByHackmd = (): JSX.Element => {
 
       const markdown = await hackmdEditorRef.current.getValue();
 
-      await saveOrUpdate(optionsToSave, { pageId, path: currentPagePath || currentPathname, revisionId: revision?._id }, markdown);
+      const { page } = await saveOrUpdate(optionsToSave, { pageId, path: currentPagePath || currentPathname, revisionId: revision?._id }, markdown);
       await mutatePageData();
       await mutateTagsInfo();
+
+      if (page == null) {
+        return;
+      }
+      await mutateIsEnabledUnsavedWarning(false);
+      await router.push(`/${page._id}`);
       mutateEditorMode(EditorMode.View);
-      mutateIsEnabledUnsavedWarning(false);
     }
     catch (error) {
       logger.error('failed to save', error);

+ 7 - 5
packages/app/src/components/UnsavedAlertDialog.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect } from 'react';
+import React, { useCallback, useEffect, memo } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { useRouter } from 'next/router';
@@ -8,9 +8,10 @@ import { useIsEnabledUnsavedWarning } from '~/stores/editor';
 const UnsavedAlertDialog = (): JSX.Element => {
   const { t } = useTranslation();
   const router = useRouter();
-  const { data: isEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
+  const { getIsEnabledUnsavedWarningFromCache } = useIsEnabledUnsavedWarning(); // Use getIsEnabledUnsavedWarningFromCache since eventListeners do not wait until states change
 
   const alertUnsavedWarningByBrowser = useCallback((e) => {
+    const isEnabledUnsavedWarning = getIsEnabledUnsavedWarningFromCache();
     if (isEnabledUnsavedWarning) {
       e.preventDefault();
       // returnValue should be set to show alert dialog
@@ -19,15 +20,16 @@ const UnsavedAlertDialog = (): JSX.Element => {
       e.returnValue = '';
       return;
     }
-  }, [isEnabledUnsavedWarning]);
+  }, [getIsEnabledUnsavedWarningFromCache]);
 
   const alertUnsavedWarningByNextRouter = useCallback(() => {
+    const isEnabledUnsavedWarning = getIsEnabledUnsavedWarningFromCache();
     if (isEnabledUnsavedWarning) {
     // eslint-disable-next-line no-alert
       window.alert(t('page_edit.changes_not_saved'));
     }
     return;
-  }, [isEnabledUnsavedWarning, t]);
+  }, [getIsEnabledUnsavedWarningFromCache, t]);
 
   /*
   * Route changes by Browser
@@ -56,4 +58,4 @@ const UnsavedAlertDialog = (): JSX.Element => {
   return <></>;
 };
 
-export default UnsavedAlertDialog;
+export default memo(UnsavedAlertDialog);

+ 17 - 3
packages/app/src/stores/editor.tsx

@@ -1,5 +1,5 @@
 import { Nullable, withUtils, SWRResponseWithUtils } from '@growi/core';
-import useSWR, { SWRResponse } from 'swr';
+import useSWR, { SWRResponse, useSWRConfig } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
 import { apiGet } from '~/client/util/apiv1-client';
@@ -114,6 +114,20 @@ export const usePageTagsForEditors = (pageId: Nullable<string>): SWRResponse<str
   };
 };
 
-export const useIsEnabledUnsavedWarning = (): SWRResponse<boolean, Error> => {
-  return useStaticSWR<boolean, Error>('isEnabledUnsavedWarning', undefined, { fallbackData: false });
+type IUtilsIsEnabledUnsavedWarning = {
+  getIsEnabledUnsavedWarningFromCache(): boolean,
+};
+
+export const useIsEnabledUnsavedWarning = (): SWRResponseWithUtils<IUtilsIsEnabledUnsavedWarning, boolean, Error> => {
+  const key = 'isEnabledUnsavedWarning';
+
+  const { cache } = useSWRConfig();
+
+  const swrResponse = useStaticSWR<boolean, Error>(key, undefined, { fallbackData: false })
+
+  return withUtils(swrResponse, {
+    getIsEnabledUnsavedWarningFromCache() {
+      return cache.get(key);
+    },
+  });
 };