2
2
3
3
import EditorJS , { OutputData } from '@editorjs/editorjs'
4
4
import { stripHtml } from 'string-strip-html'
5
- import React , { useEffect , useRef } from 'react'
5
+ import React , { useCallback , useEffect , useRef , useState } from 'react'
6
6
import {
7
7
Environment ,
8
8
graphql ,
@@ -74,6 +74,7 @@ type EditorProps = {
74
74
body ?: string
75
75
requestCookie ?: string | null
76
76
}
77
+ let isEditorInitialized = false
77
78
78
79
export default function StoryEditor ( {
79
80
editable,
@@ -89,38 +90,42 @@ export default function StoryEditor({
89
90
}
90
91
91
92
function Editor ( { editable, body } : EditorProps ) {
92
- const ejInstance = useRef < EditorJS | null > ( )
93
+ const editorRef = useRef < EditorJS > ( )
93
94
94
- const [ editorData , setEditorData ] = React . useState (
95
+ const [ editorData ] = useState (
95
96
( body && JSON . parse ( body ) ) || DEFAULT_INITIAL_DATA
96
97
)
97
- useEffect ( ( ) => {
98
- if ( ! ejInstance . current ) {
99
- initEditor ( )
100
- }
101
- return ( ) => {
102
- ejInstance ?. current ?. destroy ( )
103
- ejInstance . current = null
104
- }
105
- } , [ ] )
106
98
107
- const initEditor = ( ) => {
99
+ const getEditorContent = useCallback ( async ( ) => {
100
+ const content = await editorRef . current ?. save ( )
101
+ return content
102
+ } , [ ] )
103
+ const initEditor = useCallback ( ( ) => {
108
104
const editor = new EditorJS ( {
109
105
holder : EDITTOR_HOLDER_ID ,
110
106
data : editorData ,
107
+ placeholder : 'title' ,
108
+ defaultBlock : 'paragraph' ,
111
109
onReady : ( ) => {
112
- ejInstance . current = editor
113
- } ,
114
- onChange : async ( ) => {
115
- const content = await editor . saver . save ( )
116
- setEditorData ( content )
110
+ editorRef . current = editor
117
111
} ,
118
112
autofocus : true ,
119
113
tools : EDITOR_JS_TOOLS ,
120
114
inlineToolbar : true ,
121
115
readOnly : ! editable ,
122
116
} )
123
- }
117
+ } , [ editable , editorData ] )
118
+ useEffect ( ( ) => {
119
+ if ( ! editorRef . current && ! isEditorInitialized ) {
120
+ initEditor ( )
121
+ isEditorInitialized = true
122
+ }
123
+ return ( ) => {
124
+ editorRef ?. current ?. destroy ( )
125
+ editorRef . current = undefined
126
+ }
127
+ } , [ editorRef , initEditor ] )
128
+
124
129
const [ commitMutation ] = useMutation (
125
130
graphql `
126
131
mutation StoryEditorCreateMutation($input: StoryInput!) {
@@ -130,23 +135,26 @@ function Editor({ editable, body }: EditorProps) {
130
135
}
131
136
`
132
137
)
133
- const handleStorySubmit = ( ) => {
134
- const postTitle = getTitle ( editorData )
135
- commitMutation ( {
136
- variables : {
137
- input : {
138
- title : postTitle ,
139
- contentJson : JSON . stringify ( editorData ) ,
140
- abstractContent : getAbstract ( editorData ) ,
141
- urlSuffix : postTitle
142
- . toLowerCase ( )
143
- . replaceAll ( ' ' , '-' )
144
- . substring ( 0 , 32 ) ,
145
- thumbnail : getThubnail ( editorData ) ,
138
+ const handleStorySubmit = useCallback ( async ( ) => {
139
+ const editorContent = await getEditorContent ( )
140
+ if ( editorContent ) {
141
+ const postTitle = getTitle ( editorContent )
142
+ commitMutation ( {
143
+ variables : {
144
+ input : {
145
+ title : postTitle ,
146
+ contentJson : JSON . stringify ( editorContent ) ,
147
+ abstractContent : getAbstract ( editorContent ) ,
148
+ urlSuffix : postTitle
149
+ . toLowerCase ( )
150
+ . replaceAll ( ' ' , '-' )
151
+ . substring ( 0 , 32 ) ,
152
+ thumbnail : getThubnail ( editorContent ) ,
153
+ } ,
146
154
} ,
147
- } ,
148
- } )
149
- }
155
+ } )
156
+ }
157
+ } , [ commitMutation , getEditorContent ] )
150
158
return (
151
159
< Card classes = "prose max-w-none dark:prose-invert" >
152
160
< div className = "prose-code" >
0 commit comments