React使用EditorJS首次加载渲染两个编辑器、刷新追加新实例问题
问题根源
- 你直接把
new EditorJS()的逻辑写在了组件的顶层作用域,只要组件触发重渲染,这段初始化逻辑就会执行一次,自然会不断生成新的编辑器实例挂载到同一个容器上 - React 18+ 的开发环境默认开启严格模式,组件首次挂载时会执行「挂载→卸载→重新挂载」的流程,就算没有其他重渲染逻辑,首次加载也会触发两次初始化,所以你刚打开页面就会看到两个编辑器
修复方案
用useRef存储编辑器实例,配合useEffect控制初始化和销毁的时机,修改后的代码如下:
// react etc. imports import { useState, useRef, useEffect } from 'react' import EditorJS from '@editorjs/editorjs' const EditorComponent = (props) => { const [input, setInput] = useState({}) const currentuser = useSelector((state) => state.currentuser) // 用ref存储实例,避免重渲染丢失 const editorRef = useRef(null) useEffect(() => { // 避免重复初始化 if (editorRef.current) return // 初始化编辑器 editorRef.current = new EditorJS({ holderId: 'editorjs', autofocus: true, }) // 组件卸载/依赖更新时销毁实例 return () => { if (editorRef.current) { editorRef.current.destroy() editorRef.current = null } } }, []) // 空依赖数组,仅在组件挂载时执行一次初始化 const postNews = async () => { if (!editorRef.current) return const outputData = await editorRef.current.save() // 后续提交逻辑 } return ( <Grid> <Grid templateRows='auto min-content' gap={6}> <div id='editorjs' /> <Button onClick={postNews}>Post news</Button> </Grid> </Grid> ) }
注意事项
- 后续所有调用编辑器API的操作(比如保存内容)都要从
editorRef.current上取实例 - 如果编辑器配置有需要响应状态变化的参数,可以把对应的参数加到useEffect的依赖数组里,依赖变更时会自动销毁旧实例再创建新实例,不会重复挂载
- 不要手动操作editorjs容器的DOM,避免和EditorJS的内部逻辑冲突
内容的提问来源于stack exchange,提问作者PRSHL
相关产品推荐
相关产品推荐

