4

I have the following issue:

Unhandled Runtime Error Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of Resumos.

These different solutions didn't work:

Solution 1:


import dynamic from "next/dynamic";

const { CKEditor } = dynamic(
  () => {
    return import('@ckeditor/ckeditor5-react');
  },
  { ssr: false }
);

const {ClassicEditor} = dynamic(
  () => {
    return import('@ckeditor/ckeditor5-build-classic');
  },
  { ssr: false }
);

const Resumos = ({id}) => {
  <CKEditor 
       editor={ ClassicEditor }
       data={textoResumoAluno}
       onChange={handleChangeTextoResumoAluno}
  />
}

Solutioc 2:

const Resumos = ({id}) => {
    const editorRef = useRef()
    const [ editorLoaded, setEditorLoaded ] = useState( false )
    const { CKEditor, ClassicEditor } = editorRef.current || {}

    useEffect( () => {
        editorRef.current = {
          CKEditor: require( '@ckeditor/ckeditor5-react' ),
          ClassicEditor: require( '@ckeditor/ckeditor5-build-classic' )
        }
        setEditorLoaded( true )
    }, [] );


{editorLoaded ? ( 
      <CKEditor
           editor={ ClassicEditor }
           data={textoResumoAluno}
           onInit={ editor => { /*You can store the "editor" and use when it is needed.
                 console.log('Editor is ready to use!', editor)*/
            }}
           onChange={handleChangeTextoResumoAluno}
       /> 
  ) : (
          <div>Editor loading</div>
  )}
}
juliomalves
  • 42,130
  • 20
  • 150
  • 146
Eric
  • 147
  • 1
  • 7
  • 1
    Check these packages. They give a good idea what's exported. One is named export, another is default export. This isn't the case for trial and error. The first won't fit the comment. The second will be `CKEditor: require( '@ckeditor/ckeditor5-react' ).CKEditor, ClassicEditor: require( '@ckeditor/ckeditor5-build-classic' ).default`. – Estus Flask Mar 17 '21 at 21:58
  • Thanks! It helped me find the solution – Eric Mar 19 '21 at 19:05

2 Answers2

11

Thanks @EstusFlask, it helped me find the solution!

const Resumos = () => {
    const editorRef = useRef()
    const [ editorLoaded, setEditorLoaded ] = useState( false )
    const { CKEditor, ClassicEditor} = editorRef.current || {}

    useEffect( () => {
        editorRef.current = {
          CKEditor: require( '@ckeditor/ckeditor5-react' ).CKEditor, //Added .CKEditor
          ClassicEditor: require( '@ckeditor/ckeditor5-build-classic' ),
        }
        setEditorLoaded( true )
    }, [] );
    
   const [data, setData] = useState('');

    return( 
      <>
        {editorLoaded ? <CKEditor
            editor={ ClassicEditor }
            data={data}
            onReady={ editor => {
              // You can store the "editor" and use when it is needed.
              console.log('Editor is ready to use!', editor);           
            } }
            onChange={ (event, editor ) => {
              const data = editor.getData()
              setData(data);
            } }
        /> : <p>Carregando...</p>}
     </>
     )
}

Eric
  • 147
  • 1
  • 7
1

You can actually do it like this: https://stackoverflow.com/a/72813101/4345461

(added my version with some improvements below for less clicking around - if this helped you, please upvote the original answer too)

@/components/CKEditor/ClassicCKEditor:

"use client";

import React from "react";
import { CKEditor } from "@ckeditor/ckeditor5-react";
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";

function ClassicCKEditor({
  data,
  onChange,
}: {
  data: string;
  onChange: (event: any, editor: ClassicEditor) => void;
}) {
  return (
    <CKEditor
      editor={ClassicEditor}
      data={data}
      onReady={(editor) => {
        console.log("ClassicCKEditor is ready to use!", editor);
      }}
      onChange={(event, editor) => {
        const data = editor.getData();
        console.log({ event, editor, data });
        onChange(event, editor);
      }}
      onBlur={(event, editor) => {
        console.log("Blur.", editor);
      }}
      onFocus={(event, editor) => {
        console.log("Focus.", editor);
      }}
    />
  );
}

export default ClassicCKEditor;

EmailTemplateView.tsx

"use client";

import dynamic from "next/dynamic";
import { useCallback } from "react";

interface Params {
  uid: string;
}

interface AllParameters {
  params: Params;
  searchParams: any;
}

const ClassicCKEditor = dynamic(
  () => import("@/components/CKEditor/ClassicCKEditor"),
  { ssr: false }
);

export default function EmailTemplateView({ params }: AllParameters) {
  const onCKChange = useCallback((value: any) => {
    console.log("CK Change");
    console.log("value", value);
  }, []);

  return (
    <div>
      <h2>Using CKEditor 5 build in React</h2>

      <ClassicCKEditor
        data={"<p>Hello from CKEditor 5!</p>"}
        onChange={onCKChange}
      />
    </div>
  );
}
Filip Savic
  • 2,737
  • 1
  • 29
  • 34