Skip to content

editorjs.mjs:4749 Uncaught TypeError: Cannot read properties of undefined (reading 'classList') #2606

@Chriskuiper1

Description

@Chriskuiper1

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:

  1. I have an admin menu with tabs, one tab is for translations and here i use multiple editor.js components.
  2. When clicking the tab, the components load, all goes well.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions