React+TypeScript中EditorJS调用destroy方法报错问题求助
EditorJS在React+TS中卸载时
destroy is not a function问题解决 问题原因
你当前的代码中,editorInstance是useEffect内部的局部变量,存在两个核心问题:
- 闭包引用失效:当
initialData变化触发组件重新渲染时,新的useEffect会创建新的editorInstance,而旧的清理函数捕获的是旧作用域里的实例——此时旧实例对应的DOM已经被新实例占用,内部状态已被破坏,调用destroy时就会出现方法不存在的异常。 - 严格模式双重执行:React开发环境默认开启严格模式,会双重执行
useEffect,导致创建两个EditorJS实例。第一个实例的DOM被第二个覆盖后,其destroy方法已无法正常工作。
而使用useRef保存实例的核心原因是:useRef的.current属性在组件整个生命周期内是稳定的单一引用,不会随组件重新渲染创建新变量,能始终获取到最新的有效EditorJS实例。
修复后的代码
// Import necessary modules import React, { useRef, useEffect } from "react"; import EditorJS, { OutputData } from "@editorjs/editorjs"; import { Tools } from "./Tools"; import "./styles.css"; interface EditorProps { initialData?: OutputData; // Optional initial data in JSON format } // Define the Editor component const Editor: React.FC<EditorProps> = ({ initialData }) => { // 用useRef存储EditorJS实例,保证引用全局稳定 const editorRef = useRef<EditorJS | null>(null); // Function to handle saving the editor content const handleSave = async () => { console.log("saving content..."); if (editorRef.current) { const data = await editorRef.current.save(); // 这里实现你的保存逻辑 console.log(data); } }; // Initialize the editor when the component mounts or initialData changes useEffect(() => { // 若已有实例,先销毁再创建新的,避免DOM冲突 if (editorRef.current) { editorRef.current.destroy(); editorRef.current = null; } // Initialize EditorJS const editorInstance = new EditorJS({ holder: "editorjs", tools: Tools, initialData: initialData || undefined, }); editorInstance.isReady .then(() => console.log("Editor.js is ready to work!")) .catch((err) => console.error(err)); editorRef.current = editorInstance; // Cleanup function to destroy the editor when the component unmounts or effect re-runs return () => { if (editorRef.current) { console.log("destroying editor instance..."); editorRef.current.destroy(); editorRef.current = null; } }; }, [initialData]); return ( <div className="editor-container"> <div id="editorjs" style={{ minHeight: "300px" }}></div> <button className="save-button" onClick={handleSave}> Save </button> </div> ); }; export default Editor;
关键修改说明
- 用useRef存储实例:避免了局部变量的闭包作用域问题,确保任何时候都能获取到最新的有效实例。
- effect重执行时先销毁旧实例:当
initialData变化时,先清理旧实例再创建新的,防止多个实例争抢同一个DOM元素。 - 清理后清空ref引用:销毁实例后重置
editorRef.current,避免保留无效引用导致后续异常。
内容的提问来源于stack exchange,提问作者arcX
相关产品推荐
相关产品推荐

