abhaynikam/react-trix-rte

Encounter editor being unmounted, but something still setting the state

Opened this issue · 4 comments

mech commented

Not sure if this is related with the way I try to lazy load the editor to solve windows problem. In my Next.js, I load the editor like so:

const TrixEditor = dynamic(() => import("form-controls/TrixEditor"), {
  ssr: false,
  loading: () => <p>Loading editor...</p>,
});

However, after I navigate to elsewhere and start typing, I have this warning:

Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

at u (webpack-internal:///./node_modules/react-trix-rte/dist/index.js:1:23242)
at div
at TrixEditor (webpack-internal:///./form-controls/TrixEditor.js:92:24)
at LoadableImpl (webpack-internal:///./node_modules/next/dist/shared/lib/loadable.js:103:38)
....
mech commented

After some investigating, I found that during cleanup at the ReactTrixRTEInput's useEffect, the trixRTEInputRef is always null.

useEffect(() => {
  console.log("1. mount", trixRTEInputRef);

  if (trixRTEInputRef && trixRTEInputRef.current) {
    const { addEventListener } = trixRTEInputRef.current;
    addEventListener("trix-change", handleChange);
    if (onFocus) addEventListener("trix-focus", onFocus);
    if (onBlur) addEventListener("trix-blur", onBlur);
    if (onInitialize) addEventListener("trix-initialize", onInitialize);
    if (onFileAccepted) addEventListener("trix-file-accept", onFileAccepted);
    if (onAttachmentAdd) addEventListener("trix-attachment-add", onAttachmentAdd);
    if (onAttachmentRemove) addEventListener("trix-attachment-remove", onAttachmentRemove);
    if (onSelectionChange) addEventListener("trix-selection-change", onSelectionChange);
    if (onBeforeInitialize) addEventListener("trix-before-initialize", onBeforeInitialize);
  }

  return () => {
    console.log("2. unmount", trixRTEInputRef);

    if (trixRTEInputRef && trixRTEInputRef.current) {
      const { removeEventListener } = trixRTEInputRef.current;
      console.log("is removeEventListener been called?", trixRTEInputRef.current)
      removeEventListener("trix-change", handleChange);
      if (onFocus) removeEventListener("trix-focus", onFocus);
      if (onBlur) removeEventListener("trix-blur", onBlur);
      if (onInitialize) removeEventListener("trix-initialize", onInitialize);
      if (onFileAccepted) removeEventListener("trix-file-accept", onFileAccepted);
      if (onAttachmentAdd) removeEventListener("trix-attachment-add", onAttachmentAdd);
      if (onSelectionChange) removeEventListener("trix-selection-change", onSelectionChange);
      if (onAttachmentRemove) removeEventListener("trix-attachment-remove", onAttachmentRemove);
      if (onBeforeInitialize) removeEventListener("trix-before-initialize", onBeforeInitialize);
    }
  };
}, [])

I noticed that the console log of console.log("2. unmount", trixRTEInputRef); is always null which lead to memory issues by not cleaning up the handleChange.

mech commented

Any idea if you think you encounter this issues also? I can pretty much confirm the cleanup is not being executed. Sorry to bother once again :(

@mech Sorry I was away for a few days. I will debug this issue this weekend.

@mech I am not able to reproduce this issue in my environment. Would you be able to share some more context or reproduction sandbox? 😊