Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor.destroy() #919

Open
Doaa-Ahmed opened this issue Oct 15, 2019 · 13 comments
Open

Editor.destroy() #919

Doaa-Ahmed opened this issue Oct 15, 2019 · 13 comments

Comments

@Doaa-Ahmed
Copy link

Doaa-Ahmed commented Oct 15, 2019

I want to destroy the editor instance manually and then set it again when the component is updated.
I am using ReactJs but I am not using the react wrapper.
Whenever I try to call the destroy function I got the error that destroy is not a function.

const MyEditor = () => {
  const [editor, setEditor] = useState([]);
  useEffect(() => {
    if (editor.length != 0) { 
      editor.destroy();
    }
    setEditor(
      new EditorJS({
        holder: "editor",
        placeholder: "Insert your text here!",
        tools: {
          header: Header,
          list: List,
          quote: Quote,
          checklist: Checklist,
          code: Code,
          table: Table,
          image: {
            class: ImageTool,
            config: {
              endpoints: {
                byFile: "myFile",
                byUrl: "myUrl"
              }
            }
          }
        },
        data: {
          blocks: myBlocks
        }
      })
    );
  }, [myData]);
@neSpecc
Copy link
Member

neSpecc commented Oct 15, 2019

Make sure you call destroy() on the editor instance. Try to debug editor variable, looks like it stores something different.

@Doaa-Ahmed
Copy link
Author

Although I got this when I try to debug the editor variable.
t {isReady: Promise}
clear: ƒ ()
configuration: {holder: "editor", placeholder: "Insert your event details here!", tools: {…}, data: {…}, initialBlock: "paragraph", …}
destroy: ƒ ()
emit: ƒ (e, n)
focus: ƒ ()
isReady: Promise {: undefined}
off: ƒ (e, n)
on: ƒ (e, n)
render: ƒ (e)
save: ƒ ()
proto: Object

But it then gives me the same error that the destroy is not a function

@neSpecc
Copy link
Member

neSpecc commented Oct 15, 2019

Maybe editor is already destroyed?

@Doaa-Ahmed
Copy link
Author

Doaa-Ahmed commented Oct 15, 2019

No.
When I run the code it gives me 2 instances of the editor on the page.
So, I want the first instance to be destroyed

@neSpecc
Copy link
Member

neSpecc commented Oct 15, 2019

Ok we will test it.

@marvinside
Copy link

if (editor.length != 0) { 
    editor.destroy();
}

Looks like editor is an Array. Try editor[0].destroy()

@elda-mahaindra
Copy link

any update on this issue? I have the same problem, every time I try to destroy the editor instance, it keeps saying that the destroy is not a function.

@mohanagy
Copy link

mohanagy commented Jan 3, 2020

you can use it inside isReady
editor.isReady .then(() => { // editor.destroy(); /** Do anything you need after editor initialization */ });

@mkeida
Copy link

mkeida commented Jan 14, 2020

For anyone getting this error, editor can not be destroyed while it is loading!

@negrudev
Copy link

negrudev commented Oct 15, 2020

any updates on this matter?

I have a TypeError when running destroy() on the editor instance.

Unhandled Runtime Error
TypeError: Cannot read property 'deactivate' of null

@evanjmg
Copy link

evanjmg commented Apr 22, 2021

getting this now with read only mode

@Aestheticsuraj234
Copy link

I am facing the same issue but i will come up with some solution try this

`"use client";
import React, { useEffect, useState, MutableRefObject } from 'react';
import EditorJS from '@editorjs/editorjs';

interface UpdateEditorProps{
editorRef: MutableRefObject<EditorJS | null>
initialData: any
}

const Editor = ({ editorRef , initialData}:UpdateEditorProps) => {
const [isMounted, setIsMounted] = useState(false);

const initializeEditor = async () => {
     // @ts-ignore
     const EditorJS = (await import('@editorjs/editorjs')).default;
     // @ts-ignore
     const Header = (await import('@editorjs/header')).default;
     // @ts-ignore
     const List = (await import('@editorjs/list')).default;
     // @ts-ignore
     const Embed = (await import('@editorjs/embed')).default;
     // @ts-ignore
     const Table = (await import('@editorjs/table')).default;
     // @ts-ignore
     const Quote = (await import('@editorjs/quote')).default;
     // @ts-ignore
     const Marker = (await import('@editorjs/marker')).default;
     // @ts-ignore
     const Warning = (await import('@editorjs/warning')).default;
     // @ts-ignore
     const LinkTool = (await import('@editorjs/link')).default;
     // @ts-ignore
     const RawTool = (await import('@editorjs/raw')).default;
     // @ts-ignore
     const Delimiter = (await import('@editorjs/delimiter')).default;
     // @ts-ignore
     const InlineCode = (await import('@editorjs/inline-code')).default;
     // @ts-ignore
     const SimpleImage = (await import('@editorjs/simple-image')).default;
     // @ts-ignore
     const Checklist = (await import('@editorjs/checklist')).default;
     // @ts-ignore
     const WarningTool = (await import('@editorjs/warning')).default;
     // @ts-ignore
     const CodeBox = (await import('@bomdi/codebox')).default;


    if (!editorRef.current) {
        const editor = new EditorJS({
            holder: 'editorjs',
            onReady: () => {
                editorRef.current = editor;

            },
            placeholder: 'Type here to write your content...',
            inlineToolbar: true,
            data: initialData,
            tools: {
                header: {
                    class: Header,
                    config: {
                        placeholder: 'Enter a header',
                        levels: [1,2, 3, 4,5,6],
                        defaultLevel: 1
                    }
                },
                list: List,
                embed: Embed,
                table: Table,
                quote: Quote,
                marker: Marker,
                warning: Warning,
                code: {
                    class: CodeBox,
                    config: {
                        themeURL: 'https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/dracula.min.css',
                        themeName: 'atom-one-dark',
                    },
                },
                linkTool: {
                    class: LinkTool,
                    config: {
                        endpoint: '/api/blog/link',
                    },
                },
                raw: RawTool,
                delimiter: Delimiter,
                inlineCode: InlineCode,
                simpleImage: SimpleImage,
                checklist: Checklist,
            },
        });

        editorRef.current = editor;
    }
};

useEffect(() => {
    if (typeof window !== 'undefined') {
        setIsMounted(true);
    }
}, []);

useEffect(() => {
    const init = async () => {
        await initializeEditor();
    };

    if (isMounted) {
        init();
        return () => {
            editorRef.current?.destroy();
            editorRef.current = null;
        };
    }
}, [isMounted]);

return (
    <div className='mt-4'>
        <div id="editorjs" className="prose max-w-full border rounded-sm py-10 px-10" />
    </div>
);

}

export default Editor;
`

@ip10x
Copy link

ip10x commented Aug 22, 2024

I ran into this issue. The reason it's rendering twice is because React runs lifecycle functions like useEffect twice when in Strict Mode (which is enabled by default in development environments)

This component only renders the editor once and only destroys it if it has the destroy function (which it will only have if it is fully initialized)

import { Box } from "@chakra-ui/react";
import { useEffect, useRef } from "react";
import EditorJS from "@editorjs/editorjs";
import colors from "tailwindcss/colors";


export default function MarkdownEditor() {
  const editorRef = useRef<HTMLDivElement>(null)
  const editorInstance = useRef<EditorJS | null>(null);

  useEffect(() => {
    if (!editorRef.current || editorInstance.current) {
      return
    }

    editorInstance.current = new EditorJS({
      holder: editorRef.current,
    })

    return () => {
      if (editorInstance.current?.destroy) {
        editorInstance.current.destroy()
      }
    }
  }, [editorRef.current]);

  return (
    <Box>
      <Box ref={ editorRef }></Box>
    </Box>
  )
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants