Closed seloner closed 6 months ago
We also have the same issue using MeteorJS and React.
Getting this error a Next.js project as well.
serializeHTMLFromNodes depends slate's useIsomorphicLayoutEffect: https://github.com/ianstormtaylor/slate/blob/main/packages/slate-react/src/hooks/use-isomorphic-layout-effect.ts which relies on this logic to determine if it's running in a DOM environment or not: https://github.com/ianstormtaylor/slate/blob/main/packages/slate-react/src/utils/environment.ts#L48-L51
Another possible culprit for this warning is the dependency on https://github.com/udecode/plate/blob/main/packages/serializers/html/src/serializer/serializeHTMLFromNodes.ts#L1
Another common cause of this issue is having something that defines window (e.g. Jest or jsdom iirc).
It could also be caused by one of many other dependencies. But overall it does not appear to be something that Plate is causing deliberately (though it's possible I've missed something of course).
A semi-dirty way to solve this in Next.js environments is something like if (!process.browser) React.useLayoutEffect = React.useEffect;
I found the warning happens on client because the serializeHTMLFromNodes function is using React.renderToStaticMarkup . This function throws the warning. https://github.com/facebook/react/blob/main/packages/react-dom/src/server/ReactPartialRendererHooks.js#L411
To add to it, serializeHtml
(renamed?) seems to be passing a new Slate element initialized with the value we want to serialize into the renderStaticMarkup
call. The renderStaticMarkup
function is from react-dom-server
instead of react-dom
, so the dispatcher for useLayoutEffect
targets the server package instead of the client package, even though it's executing on the client. That's why the CAN_USE_DOM
or other typeof window...
checks don't prevent the issue.
So when this Slate element (which seems to be rendered in a server module on the client side) sets useIsomorphicLayoutEffect
, it's passing the client-side check, but React dispatches the server-side useLayoutEffect function through react-server-dom
, which is just a placeholder that prints that error.
I can't think of a great solution. The simplest solution would be to add an option to Slate that allows you to force useIsomorphicLayoutEffect
to point to useEffect
, then pass in that flag when calling renderStaticMarkup
. Otherwise, I wonder if it would work to use slate-react-presentation or some other method to generate the element that goes into the renderStaticMarkup
call?
Thoughts @zbeyens?
Makes a lot of sense.
renderStaticMarkup
was used as the quickest DRY solution, I'm open to any other alternatives. Otherwise I'm sure @dylans would quickly review your suggested option to Slate.
@zbeyens, when serializing from the contents of an existing Slate/Plate instance (instead of an editor data object), what about applying a simple container ref
:
<Plate renderEditable={(children) => (
<div ref={editorContents}>
{children}
</div>
)}
/>
...and normalizing the HTML string from editorContents.current.innerHtml
? It seems like it would mostly be a matter of stripping out Slate <span>
tags and removing unwanted classnames. Would that be viable?
If that would work, it might also be a suitable alternate strategy for renderStaticMarkup
while serializing a raw data object as well.
Worth a try. How would we use it server-side?
Description
serializeHTMLFromNodes cause warnings in nextjs
I am getting this warning
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See
Environment
Funding