8

I would like to implement CKEditor into my react project. However, I received an error while trying to load it. I have been following all the official documentation. I have no idea why, anyway here is my code

import React from 'react';

class MyEditor extends React.Component {
    state = {loading: true};

    componentDidMount() {
        this.CKEditor = require("@ckeditor/ckeditor5-react");
        this.ClassicEditor = require("@ckeditor/ckeditor5-build-classic");
        this.setState({ loading: false }); 
    }

    render() {
        return ({this.CKEditor && (<this.CKEditor editor={this.ClassicEditor} data="<p>Hello from CKEditor 5!</p>"
                onInit={ 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();
                    console.log( { event, editor, data } );
                } }/>)})
    }
}

export default MyEditor;

I receive this following error

ReferenceError: window is not defined at Object. (/Users/bobbyjulian/Desktop/project/test/node_modules/ ckeditor/ckeditor5-react/dist/ckeditor.js:5:244 Module._compile internal/modules/cjs/loader.js:778:30 Module._extensions..js internal/modules/cjs/loader.js:789:10 Module.load internal/modules/cjs/loader.js:653:32 tryModuleLoad internal/modules/cjs/loader.js:593:12

I really appreciate any answer. Thank you.

4
  • 1
    Is it rendered server side? NextJs? Commented Oct 18, 2019 at 8:46
  • sure, its NextJs Commented Oct 18, 2019 at 8:59
  • if remix brought you here, export the CKEditor component from a file with extension *.client.tsx to prevent it from getting rendered on the server Commented Feb 10, 2023 at 1:53
  • or maybe wrap in <ClientOnly> Commented Feb 10, 2023 at 18:36

3 Answers 3

31

Here's a working example with NextJS and React Hooks. We can take advantage of useRef to hold on to the Editor instances.

import React, { useState, useEffect, useRef } from 'react'

export default function MyEditor () {
  const editorRef = useRef()
  const [editorLoaded, setEditorLoaded] = useState(false)
  const { CKEditor, ClassicEditor } = editorRef.current || {}

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

  return editorLoaded ? (
    <CKEditor
      editor={ClassicEditor}
      data='<p>Hello from CKEditor 5!</p>'
      onInit={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()
        console.log({ event, editor, data })
      }}
    />
  ) : (
    <div>Editor loading</div>
  )
}

From the docs:

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

Sign up to request clarification or add additional context in comments.

4 Comments

I ended up making a custom hook for this, which you can find here: gist.github.com/arcdev1/aba0fcea9f618de42ca399e3266f42aa
Perfect, Bill. =)
If you are using CKEditor 3.0.0 and above, the default import was removed so change: CKEditor: require('@ckeditor/ckeditor5-react'), Into: CKEditor: require('@ckeditor/ckeditor5-react').CKEditor,
Thanks @omerts ... updated the code in my answer to reflect this.
4

If you are doing server side rendering then you need to load your CKeditor dynamically, because it interacts with the DOM thus, on server since there is no browser it throws this Error.

 class MyEditor extends React.Component {
  state = { loading: true };

  componentDidMount() {
    this.CKEditor = require("@ckeditor/ckeditor5-react");
    this.ClassicEditor = require("@ckeditor/ckeditor5-build-classic");
    this.setState({ loading: false });
  }

  render() {
    return this.CKEditor ? (
      <this.CKEditor
        editor={this.ClassicEditor}
        data="<p>Hello from CKEditor 5!</p>"
        onInit={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();
          console.log({ event, editor, data });
        }}
      />
    ) : (
      <div>Editor loading</div>
    );
  }
}

6 Comments

Hi, I have tried your code but I got an error './components/TextEditor.js SyntaxError: /Users/bobbyjulian/Desktop/project/test/components/TextEditor.js: Unexpected token (1:13)' FYI I am doing SSR with NextJs
can you share the exact code after the change? I think i wrote from as 'form' in the first line. can you recheck that
hi, I have edit the code above. Please kindly check it. Thank you
There is a typo on the imprt it should be from and not form
Hi, I have fixed the typo but its still error './components/TextEditor.js SyntaxError: /Users/bobbyjulian/Desktop/project/test/components/TextEditor.js: Unexpected keyword 'this' (13:17)'
|
2

Dynamic import will solve this issue

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.