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

TypeError: Cannot read properties of null (reading 'model') / Watchdog causing issues with quick rerender #370

Closed
HarunKaranja opened this issue Mar 30, 2023 · 15 comments · Fixed by ckeditor/ckeditor5#15981
Labels
domain:dx support:2 An issue reported by a commercially licensed client. type:bug
Milestone

Comments

@HarunKaranja
Copy link

I am trying to create an image uploader but am facing an issue TypeError: Cannot read properties of null (reading 'model')

Here is my code

import { CKEditor } from "@ckeditor/ckeditor5-react";
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
import axios from "axios";
import { apiUrl, url } from "@/constants";

const Editor = ({ value, onChange }) => {
  const uploadAdapter = (loader) => {
    return {
      upload: () => {
        return new Promise((resolve, reject) => {
          const formData = new FormData();
          const uri = apiUrl + "upload";

          loader.file.then((file) => {
            formData.append("image", file, file.name);

            axios
              .post(uri, formData, {
                headers: { "Content-Type": "multipart/form-data" },
              })
              .then((res) => res.data)
              .then((data) => {
                resolve({ default: url + "uploads/products/" + data.name });
              })
              .catch((error) => {
                reject(error);
              });
          });
        });
      },
    };
  };

  const uploadPlugin = (editor) => {
    editor.plugins.get("FileRepository").createUploadAdapter = (loader) => {
      return uploadAdapter(loader);
    };
  };

  return (
    <div className="edito">
      <CKEditor
        config={{
          extraPlugins: [uploadPlugin],
        }}
        editor={ClassicEditor}
        data={value}
        onChange={(event, editor) => {
          onChange(editor.getData());
        }}
      />
    </div>
  );
};

export default Editor;

When i comment out the following section there's no issue

 config={{
          extraPlugins: [uploadPlugin],
        }}

This is the use case on the page since am using next js

const description = useRef("");

const Editor = dynamic(() => import("../editor"), { ssr: false });


<Editor
      value={description.current}
      onChange={(e) => {
        description.current = e;
      }}
    />
@jabrij93
Copy link

I am getting the same errror, i am using react version v5.1.0

@daniyelgamit
Copy link

I'm facing the same issue with react version 6.0.0

image

@Witoso
Copy link
Member

Witoso commented May 25, 2023

I think the OP problem may be related to the Next.js 🤔 @Mgsy or @LukaszGudel have you seen something like this?

@laogui
Copy link

laogui commented Jun 7, 2023

Is there any update on this issue? I have same problem on 6.0.

@rujal408
Copy link

I have the same problem too

@Witoso
Copy link
Member

Witoso commented Jun 20, 2023

I cannot find the corresponding issue, but I remember that one change somehow made it work in some other case. It was a switch from the arrow function assigned to a variable to a function declaration:

Change this

const uploadPlugin = (editor) => { // ...

To this

function uploadPlugin(editor) { //...

and maybe other variable functions as well. Could you check @rujal408?

@rujal408
Copy link

@Witoso, this solution is not feasible as we have not used uploadPlugin function. Is there any other way ?

@AliaksandrBortnik
Copy link

AliaksandrBortnik commented Aug 17, 2023

Plain 17-th React. No SSR. The same issue on destroy sometimes.

"@ckeditor/ckeditor5-react": "6.0.0"
+ deps 38.1.0 under the hood.

image

UPD:
Just updated ckeditor5-react from 6.0.0 to 6.1.0 and leveraged disableWatchdog={true}. No surprise, the error dissapeared since no watchdog now. However, as for now, I am going to keep 6.0.0 as is and start digging into the issue of watchdog.

@Witoso
Copy link
Member

Witoso commented Aug 17, 2023

It would be great to have some reproducible sample, as there are many ways of bundling the editor and React (and Next.js from the OP). Could someone provide it?

@AliaksandrBortnik
Copy link

AliaksandrBortnik commented Aug 22, 2023

Is it correct implementation to have the 151th _stopErrorHandling() and then trying to remove change:data event handler on 159-th line? editorwatchdog.js.

image

_stopErrorHandling() is a part of watchdog.js.

image

Wouldn't it be better to remove event handler for errors at the end calling _stopErrorHandling() instead of 151th line? It is obvisously not the reason of this._editor appears null by some unknown reason yet, but just to be safe.

@AliaksandrBortnik
Copy link

After some investigation within a complex solution, I'm ready to share how it happens that this error is raised by CKE5 and its watchdog feature under the hood in particular.

In my case, there is a custom build from sources. Thus, I removed all plugins except Essentials as the first step, but an error still existed.

The root issue is that there are multiple very fast rerenders on the parent level. Hence, editor appears null in such cases. See the screenshot above: 154th line. So, CKE5 is trying to destroy when it seems the editor has not been fully created yet.

To eliminate such an error, you should either:

  1. Investigate data flow on the parent level and prevent redundant rerenders that causes CKE5 instance full recreation process.
  2. OR use >=6.1.0 version of @ckeditor5-react that provides a new prop to completely turn off watchdog feature.

@Witoso
Copy link
Member

Witoso commented Aug 25, 2023

Hey @AliaksandrBortnik!

Is it correct implementation to have the 151th _stopErrorHandling() and then trying to remove change:data event handler on 159-th line? editorwatchdog.js.

As far as I understand, it's not needed. One is closing the error listening, the other is to prevent the possible triggers of watchdog and its data preservation mechanism. Two distinct cases.

The root issue is that there are multiple very fast rerenders on the parent level.

Very interesting, thanks for the deep dive. What's the use case on your side? Is it testing related?

@AliaksandrBortnik
Copy link

AliaksandrBortnik commented Aug 25, 2023

@Witoso absolutely not related to any kind of testing at all. In my case, on one of higher level, there was a quick force update via key prop. It seems watchdog was not able to get a newly created instance so fast at the time it should start destroying.

In other words, React's key value has been quickly changed and then the same component unmounted very fast. So, watchdog had to recreate an instance of CKE5 (when key is changed) and instantly start destroying. Thus, watchdog had to start the destroy process in the moment when a creation phase is probably still in progress => no model ready to destroy.

Promise rejection happens on editor.model.document.off("change:data") because there is no editor. Editor is null.

@AliaksandrBortnik
Copy link

We caught two such places in our codebase. The simple reason of the error is that on a parent level we do complete DOM destroy for a React sub-tree of components, and recreate it quickly. E.g. we async load something with a content placeholder wrapper which do not render children (including CKE5 inside as a child) if isLoading content now.

CKE5 watchdog cannot construct everything so fast at the time we request destroy of CKE5 instance. This is why CKE5 watchdog raises promise rejection.

To solve it, some redundant updates were eliminated.

@Witoso
Copy link
Member

Witoso commented Sep 9, 2023

Thanks for the details, I will add the links to our watchdog <> react improvements notes.

@Witoso Witoso changed the title TypeError: Cannot read properties of null (reading 'model') TypeError: Cannot read properties of null (reading 'model') / Watchdog causing issues with quick rerender Sep 9, 2023
leadegroot added a commit to uqlibrary/fez-frontend that referenced this issue Nov 27, 2023
@FilipTokarski FilipTokarski added the support:2 An issue reported by a commercially licensed client. label Feb 9, 2024
@CKEditorBot CKEditorBot added this to the iteration 73 milestone Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:dx support:2 An issue reported by a commercially licensed client. type:bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants