You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 00:45:03