rich-markdown-editor
rich-markdown-editor copied to clipboard
Content is not rendered when using SSR
Hello, trying to use this library with Nextjs, but the content is not getting rendered server side
Expected behavior Content should be rendered
Version 11.0.1
Prosemirror does not support node, so to achieve this we'd have to write a renderer that emulates the output of Prosemirror – Remirror has done a good job of this, so it could be an inspiration for the work:
https://github.com/remirror/remirror/tree/master/@remirror/react-ssr
https://github.com/remirror/remirror/blob/997eb56a49ad653544fcd00b83e394e63df3a116/packages/%40remirror/react/src/renderers/react-serializer.tsx#L146
Alright, thanks!
Hi @tommoor,
I get your point about Remirror, but I would expect it to work using dynamic imports with Next.js:
const Editor = dynamic(() => import('rich-markdown-editor'), {ssr: false})
const MySSRComponent = () => {
return (
<>
{
!process.browser
? null
: (
<Editor
id={/* my id */}
defaultValue='Default value'
placeholder='Placeholder'
onChange={console.log}
/>
)
}
</>
)
}
but it's not working anyway... any idea on that?
I would expect it to work using dynamic imports with Next.js
Me too, Next must be rendering that on the server side?
I would expect it to work using dynamic imports with Next.js
Me too, Next must be rendering that on the server side?
I've specified {ssr: false} to the dynamic import options and checked if process.browser was truthy on the client side before rendering, but it's not showing up
You can create a component outside the "Page" folder and then import it dynamically inside.
import dynamic from "next/dynamic";
const Example = dynamic(() => import("../Components/<componentName>.js"), { ssr: false });
export default Example;
"Example" in this case is from the example/src/index.js file
@tarsenidze
You can create a component outside the "Page" folder and then import it dynamically inside.
Does not work.
After lots of trial and error, I think I found a workaround that seems to work quite reliably.
import React, { memo, useEffect, useState } from "react";
import RichMarkdownEditor from "rich-markdown-editor";
import { Router } from "next/router";
const MarkdownDisplay = ({ value }: { value: string }) => {
const [render, setRender] = useState(false);
useEffect(() => {
const handle = () => {
// it doesn't work without setTimeout but I don't know why
setTimeout(() => setRender(true));
};
// bind to window load event for ssr and route change event for csr
window.addEventListener("load", handle);
Router.events.on("routeChangeComplete", handle);
return () => {
window.removeEventListener("load", handle);
Router.events.off("routeChangeComplete", handle);
};
}, []);
// render the editor initially with an empty string until the document is completely loaded
// this is important because the change in value causes prosemirror to rerender the dom correctly on the client later
return <RichMarkdownEditor value={render ? value : ""} onChange={() => {}} readOnly />;
};
export default memo(MarkdownDisplay);
This workaround should make the editor render correctly, but only on the client. It won't be visible immediately when the page is refreshed, so there will be some waiting time for the document to load until you see something. I really find it quite unfortunate that we can't take advantage of server side rendering with this editor.
Any update on this ?
I'm not planning on working on this at the moment, my applications do not use SSR. However if someone else wants to enable this functionality a PR would be happily accepted
I didn't show (loading ? <Spinner/> : <Editor/>) the Markdown editor before routeChangeComplete event, this worked instead (even with navigating between two [slug].tsx dynamic pages containing this component):
const Editor: FC<{ value: string }> = ({ value }) => {
const [render, setRender] = useState(false);
useEffect(() => {
setRender(true);
}, []);
return (
<RichMarkdownEditor value={render ? value : undefined} />
);
};
I wanted my content to get rendered as a static page (ie, rendered at build-time), so I used the react-markdown library to display the content on the server-side (since it supports SSR), then I swapped it with rich-markdown-editor on client render. This is hacky, and the initial styles that react-markdown uses are not great so there's a flicker when rich-markdown-editor is loading, but at least the content is being rendered statically.