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

slate-react 0.62.0+ - Crash if initial render's root node is not the document (reakit Portal) #4267

Closed
JackRobards opened this issue May 18, 2021 · 8 comments · Fixed by #4427
Labels

Comments

@JackRobards
Copy link

JackRobards commented May 18, 2021

Description
Since the change in slate v0.62.0 from this PR, the editor will cause a crash if the root node for it's initial render is not the document. Version 0.61.3 does not have this issue.

Notably, this happens if trying to use the slate editor in conjunction with the reakit Portal, or a similarly built component. Right now, the latest version of slate's editor does not work with the reakit Portal out of the box and trying to use them together causes a crash. In essence the problem is that if for some reason a component renders the editor before it is a child of the document, then it causes a crash.

Recording
Shouldn't be needed, open sandbox to see error.

Sandbox
https://codesandbox.io/s/slate-reproduction-reakit-portal-fk002

Steps
To reproduce the behavior:

  1. Click on either the "Toggle Basic Portal" or "Toggle Reakit Portal" buttons.
  2. See Unable to find DocumentOrShadowRoot for editor element: [object HTMLDivElement] error.
  3. If you change the versions of slate and slate-react back to 0.61.3, then there is no error when you click either button.

Expectation
Ideally there would be no error thrown, similar to how it worked in previous versions. I'm not exactly sure what this error is trying to protect against though, so it may be needed. Any insight on the purpose of the thrown error though would be appreciated!

Environment

  • Slate Version: [e.g. 0.59] 0.62.0+
  • Operating System: [e.g. iOS] Mac
  • Browser: [e.g. Chrome, Safari] Chrome, Firefox, Safari

Context
The sandbox includes a simplified version of the reakit portal implementation to hopefully make it a bit easier to debug and see what is going on. Basically, the portal is created using createPortal and then appended to the document after that. So, for the initial render it's root node is not the document and then the error is thrown causing a crash.

This issue can be worked around by delaying the rendering of the slate editor inside of the Portal until it's finished mounting completely for anyone that does encounter something similar.

@JackRobards JackRobards changed the title slate-react 0.62.0+ - Crash if initial render's root node is not the document (reakit Portal slate-react 0.62.0+ - Crash if initial render's root node is not the document (reakit Portal) May 18, 2021
@cmditch
Copy link
Contributor

cmditch commented May 31, 2021

Also seeing this error using Slate wrapped in a custom element within an Elm app.

Edit: I was able to fix the issue I was seeing and use 0.63.

The issue was due to improper unmounting of the react component within my custom element. I suspect this is due to the interaction between Elm's vdom, my custom element, and the Slate react component rendered inside the custom element.

This event listener was not being removed properly here, so all selection changes where throwing errors in my app once the slate custom element left the DOM. The error would persist on every mouse click even if a new editor was added to the DOM.

The fix was to call ReactDOM.unmountComponentAtNode within my custom element's disconnectedCallback.

@hanford
Copy link
Contributor

hanford commented Jun 2, 2021

I'm also running into this exception when I have a slate editor on a page and navigate away from that page while the editor is focused

@mfranzs
Copy link

mfranzs commented Jun 17, 2021

I believe that this is an issue in the way that throttled is being used in the selection event listener. If the selection is triggered twice within 100ms of the editor unmounting, then the callback will trigger again on the falling end of throttled after the editor has unmounted. We might be able to fix this by calling .cancel() on the throttled function before unmount.

@hanshs
Copy link

hanshs commented Jul 14, 2021

Also getting the same error when trying to render Slate editor inside a Headless UI Dialog component

@sevaplan sevaplan mentioned this issue Jul 17, 2021
5 tasks
@sevaplan
Copy link

@mfranzs yeah this is definitely this, https://github.com/ianstormtaylor/slate/pull/4382/files this fixes it

@sevaplan
Copy link

I closed the PR as I think it must be fixed a bit differently, as right now it is not correct — throttled event will happen even if callback changes, it needs to cancel throttle also if callback changes, and this requires a bit more work which I am not ready to commit to, but it would be great to fix as now it is not usable..

@baptisteArno
Copy link

Is there a workaround?

The fix was to call ReactDOM.unmountComponentAtNode within my custom element's disconnectedCallback.

I tried this:

useEffect(() => {
    return () => {
      if (!editorContainer.current) return;
      ReactDOM.unmountComponentAtNode(editorContainer.current);
    };
  }, []);

But, it doesn't fix the bug. HELP!

@dmarkow
Copy link
Contributor

dmarkow commented Jul 26, 2021

Running into the same issue trying to use slate inside a Dialog (modal) from https://github.com/tailwindlabs/headlessui – they're using createPortal from react-dom.

Rolling back to 0.61 got it working for now. Also, keeping the current version but commenting out the line that throws the error at https://github.com/davidruisinger/slate/blob/master/packages/slate-react/src/plugin/react-editor.ts#L113 seems to work too.

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