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

add WrappedEditor and import dynamically

Yuki Takei 3 лет назад
Родитель
Сommit
cf05032a8a

+ 7 - 8
packages/app/src/components/PageComment/CommentEditor.tsx

@@ -3,12 +3,14 @@ import React, {
 } from 'react';
 } from 'react';
 
 
 import { UserPicture } from '@growi/ui';
 import { UserPicture } from '@growi/ui';
+import dynamic from 'next/dynamic';
 import {
 import {
   Button, TabContent, TabPane,
   Button, TabContent, TabPane,
 } from 'reactstrap';
 } from 'reactstrap';
 import * as toastr from 'toastr';
 import * as toastr from 'toastr';
 
 
 import { apiPostForm } from '~/client/util/apiv1-client';
 import { apiPostForm } from '~/client/util/apiv1-client';
+import { IEditorMethods } from '~/interfaces/editor-methods';
 import { RendererOptions } from '~/services/renderer/renderer';
 import { RendererOptions } from '~/services/renderer/renderer';
 import { useSWRxPageComment } from '~/stores/comment';
 import { useSWRxPageComment } from '~/stores/comment';
 import {
 import {
@@ -19,7 +21,6 @@ import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 
 
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import NotAvailableForGuest from '../NotAvailableForGuest';
 import NotAvailableForGuest from '../NotAvailableForGuest';
-import Editor from '../PageEditor/Editor';
 import { SlackNotification } from '../SlackNotification';
 import { SlackNotification } from '../SlackNotification';
 
 
 import { CommentPreview } from './CommentPreview';
 import { CommentPreview } from './CommentPreview';
@@ -27,6 +28,9 @@ import { CommentPreview } from './CommentPreview';
 import styles from './CommentEditor.module.scss';
 import styles from './CommentEditor.module.scss';
 
 
 
 
+const Editor = dynamic(() => import('../PageEditor/WrappedEditor'), { ssr: false });
+
+
 const navTabMapping = {
 const navTabMapping = {
   comment_editor: {
   comment_editor: {
     Icon: () => <i className="icon-settings" />,
     Icon: () => <i className="icon-settings" />,
@@ -50,11 +54,6 @@ export type CommentEditorProps = {
   onCommentButtonClicked?: () => void,
   onCommentButtonClicked?: () => void,
 }
 }
 
 
-type EditorRef = {
-  setValue: (value: string) => void,
-  insertText: (text: string) => void,
-  terminateUploadingState: () => void,
-}
 
 
 export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
 export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
 
 
@@ -80,7 +79,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
   const [error, setError] = useState();
   const [error, setError] = useState();
   const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
   const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
 
 
-  const editorRef = useRef<EditorRef>(null);
+  const editorRef = useRef<IEditorMethods>(null);
 
 
   const handleSelect = useCallback((activeTab: string) => {
   const handleSelect = useCallback((activeTab: string) => {
     setActiveTab(activeTab);
     setActiveTab(activeTab);
@@ -260,7 +259,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
           <TabContent activeTab={activeTab}>
           <TabContent activeTab={activeTab}>
             <TabPane tabId="comment_editor">
             <TabPane tabId="comment_editor">
               <Editor
               <Editor
-                ref={editorRef}
+                editorRef={editorRef}
                 value={comment}
                 value={comment}
                 isUploadable={isUploadable}
                 isUploadable={isUploadable}
                 isUploadableFile={isUploadableFile}
                 isUploadableFile={isUploadableFile}

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

@@ -6,11 +6,13 @@ import EventEmitter from 'events';
 
 
 import { envUtils, PageGrant } from '@growi/core';
 import { envUtils, PageGrant } from '@growi/core';
 import detectIndent from 'detect-indent';
 import detectIndent from 'detect-indent';
+import dynamic from 'next/dynamic';
 import { throttle, debounce } from 'throttle-debounce';
 import { throttle, debounce } from 'throttle-debounce';
 
 
 import { saveOrUpdate } from '~/client/services/page-operation';
 import { saveOrUpdate } from '~/client/services/page-operation';
 import { apiGet, apiPostForm } from '~/client/util/apiv1-client';
 import { apiGet, apiPostForm } from '~/client/util/apiv1-client';
 import { getOptionsToSave } from '~/client/util/editor';
 import { getOptionsToSave } from '~/client/util/editor';
+import { IEditorMethods } from '~/interfaces/editor-methods';
 import {
 import {
   useIsEditable, useIsIndentSizeForced, useCurrentPagePath, useCurrentPathname, useCurrentPageId, useIsUploadableFile, useIsUploadableImage,
   useIsEditable, useIsIndentSizeForced, useCurrentPagePath, useCurrentPathname, useCurrentPageId, useIsUploadableFile, useIsUploadableImage,
 } from '~/stores/context';
 } from '~/stores/context';
@@ -28,9 +30,11 @@ import loggerFactory from '~/utils/logger';
 
 
 
 
 // import { ConflictDiffModal } from './PageEditor/ConflictDiffModal';
 // import { ConflictDiffModal } from './PageEditor/ConflictDiffModal';
-import Editor from './PageEditor/Editor';
 import Preview from './PageEditor/Preview';
 import Preview from './PageEditor/Preview';
 import scrollSyncHelper from './PageEditor/ScrollSyncHelper';
 import scrollSyncHelper from './PageEditor/ScrollSyncHelper';
+// import Editor from './PageEditor/WrappedEditor';
+
+const Editor = dynamic(() => import('./PageEditor/WrappedEditor'), { ssr: false });
 
 
 
 
 const logger = loggerFactory('growi:PageEditor');
 const logger = loggerFactory('growi:PageEditor');
@@ -39,14 +43,6 @@ const logger = loggerFactory('growi:PageEditor');
 declare const globalEmitter: EventEmitter;
 declare const globalEmitter: EventEmitter;
 
 
 
 
-type EditorRef = {
-  setValue: (markdown: string) => void,
-  setCaretLine: (line: number) => void,
-  insertText: (text: string) => void,
-  forceToFocus: () => void,
-  terminateUploadingState: () => void,
-}
-
 // for scrolling
 // for scrolling
 let lastScrolledDateWithCursor: Date | null = null;
 let lastScrolledDateWithCursor: Date | null = null;
 let isOriginOfScrollSyncEditor = false;
 let isOriginOfScrollSyncEditor = false;
@@ -84,7 +80,7 @@ const PageEditor = React.memo((): JSX.Element => {
   const slackChannels = useMemo(() => (slackChannelsData ? slackChannelsData.toString() : ''), [slackChannelsData]);
   const slackChannels = useMemo(() => (slackChannelsData ? slackChannelsData.toString() : ''), [slackChannelsData]);
 
 
 
 
-  const editorRef = useRef<EditorRef>(null);
+  const editorRef = useRef<IEditorMethods>(null);
   const previewRef = useRef<HTMLDivElement>(null);
   const previewRef = useRef<HTMLDivElement>(null);
 
 
   const setMarkdownWithDebounce = useMemo(() => debounce(100, throttle(150, (value: string, isClean: boolean) => {
   const setMarkdownWithDebounce = useMemo(() => debounce(100, throttle(150, (value: string, isClean: boolean) => {
@@ -399,7 +395,7 @@ const PageEditor = React.memo((): JSX.Element => {
     <div className="d-flex flex-wrap">
     <div className="d-flex flex-wrap">
       <div className="page-editor-editor-container flex-grow-1 flex-basis-0 mw-0">
       <div className="page-editor-editor-container flex-grow-1 flex-basis-0 mw-0">
         <Editor
         <Editor
-          ref={editorRef}
+          editorRef={editorRef}
           value={initialValue}
           value={initialValue}
           isUploadable={isUploadable}
           isUploadable={isUploadable}
           isUploadableFile={isUploadableFile}
           isUploadableFile={isUploadableFile}

+ 1 - 1
packages/app/src/components/PageEditor/Editor.tsx

@@ -22,7 +22,7 @@ import TextAreaEditor from './TextAreaEditor';
 
 
 import styles from './Editor.module.scss';
 import styles from './Editor.module.scss';
 
 
-type EditorPropsType = {
+export type EditorPropsType = {
   value?: string,
   value?: string,
   isGfmMode?: boolean,
   isGfmMode?: boolean,
   noCdn?: boolean,
   noCdn?: boolean,

+ 18 - 0
packages/app/src/components/PageEditor/WrappedEditor.tsx

@@ -0,0 +1,18 @@
+// workaround to use ref with dynamically imported components
+// see: https://github.com/vercel/next.js/issues/4957#issuecomment-783482041
+
+import React, { Ref } from 'react';
+
+import { IEditorMethods } from '~/interfaces/editor-methods';
+
+import Editor, { EditorPropsType } from './Editor';
+
+type Props = EditorPropsType & {
+  editorRef: Ref<IEditorMethods>,
+}
+
+const WrappedEditor = (props: Props): JSX.Element => {
+  return <Editor {...props} ref={props.editorRef} />;
+};
+
+export default WrappedEditor;