-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Closed
Labels
Description
Describe the bug.
Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'classList')
Call Stack
Ko.close
node_modules\@editorjs\editorjs\dist\editorjs.mjs (4745:0)
bi.documentClicked
node_modules\@editorjs\editorjs\dist\editorjs.mjs (9305:0)
HTMLDocument.eval
node_modules\@editorjs\editorjs\dist\editorjs.mjs (9190:0)
/**
* Close the Toolbar
*/
close() {
var e;
this.Editor.ReadOnly.isEnabled || (this.nodes.wrapper.classList.remove(this.CSS.toolbarOpened), >>>>> Error on this line!
this.blockActions.hide(),
(e = this.toolboxInstance) == null || e.close(),
this.Editor.BlockSettings.close());
}
Steps to reproduce:
- I have an admin menu with tabs, one tab is for translations and here i use multiple editor.js components.
- When clicking the tab, the components load, all goes well.
- However, when moving to the next tab, while the editor.js component is still loading, this error pops up.
Versions:
"@editorjs/editorjs": "^2.28.2",
"editorjs-html": "^3.4.3",
"editorjs-react-renderer": "^3.5.1",
"@editorjs/checklist": "^1.5.0",
"@editorjs/code": "^2.8.0",
"@editorjs/delimiter": "^1.3.0",
"@editorjs/embed": "^2.5.3",
"@editorjs/header": "^2.7.0",
"@editorjs/image": "^2.8.1",
"@editorjs/inline-code": "^1.4.0",
"@editorjs/link": "^2.5.0",
"@editorjs/list": "^1.8.0",
"@editorjs/marker": "^1.3.0",
"@editorjs/paragraph": "^2.9.0",
"@editorjs/quote": "^2.5.0",
"@editorjs/raw": "^2.4.0",
"@editorjs/simple-image": "^1.5.1",
"@editorjs/table": "^2.2.2",
"@editorjs/warning": "^1.3.0"
Environment: NextJS application.
Editor.js implementation:
import React, { useState, useEffect, useRef } from 'react';
let uniqueId = 0;
export default function Editor({ data, setData }) {
const [isMounted, setIsMounted] = useState(false);
const [isLoading, setIsLoading] = useState(true); // Loading state
const editorId = useRef(`editor-${uniqueId++}`);
const editorInstance = useRef();
const isComponentMounted = useRef(true); // Add this ref to track mount status
const initializeEditor = async () => {
setIsLoading(true); // Start loading
const EditorJS = (await import('@editorjs/editorjs')).default;
const Header = (await import('@editorjs/header')).default;
const Checklist = (await import('@editorjs/checklist')).default;
const Code = (await import('@editorjs/code')).default;
const Delimiter = (await import('@editorjs/delimiter')).default;
const Embed = (await import('@editorjs/embed')).default;
// const Image = (await import('@editorjs/image')).default;
const InlineCode = (await import('@editorjs/inline-code')).default;
const LinkTool = (await import('@editorjs/link')).default;
const List = (await import('@editorjs/list')).default;
const Marker = (await import('@editorjs/marker')).default;
const Paragraph = (await import('@editorjs/paragraph')).default;
const Quote = (await import('@editorjs/quote')).default;
const Raw = (await import('@editorjs/raw')).default;
// const SimpleImage = (await import('@editorjs/simple-image')).default;
const Table = (await import('@editorjs/table')).default;
const Warning = (await import('@editorjs/warning')).default;
if (!isComponentMounted.current) {
return;
}
const editor = new EditorJS({
holder: editorId.current,
tools: {
header: Header,
checklist: Checklist,
code: Code,
delimiter: Delimiter,
embed: Embed,
inlineCode: InlineCode,
list: List,
linktool: LinkTool,
paragraph: {
class: Paragraph,
inlineToolbar: ['bold', 'italic', 'link', 'marker'], // Enable inline toolbar for paragraph
},
marker: Marker,
quote: Quote,
raw: Raw,
table: Table,
warning: Warning,
},
data: data,
onChange: async () => {
if (editor && typeof editor.save === 'function') {
const outputData = await editor.save();
setData(outputData);
}
}
});
editorInstance.current = editor;
setIsLoading(false); // Finish loading
};
useEffect(() => {
if (typeof window !== 'undefined') {
setIsMounted(true);
}
}, []);
useEffect(() => {
if (isMounted) {
initializeEditor();
return () => {
if (editorInstance.current && typeof editorInstance.current.destroy === 'function') {
editorInstance.current.destroy();
editorInstance.current = null;
}
isComponentMounted.current = false; // Set to false on unmount
};
}
}, [isMounted]);
if (isLoading) {
return <div>Loading Editor...</div>;
}
return (
<div id={editorId.current} />
);
}
Device, Browser, OS: Google Chrome as desktop browser.