Skip to main content

Frequently Asked Questions

Some of the answers outlined here may be helpful to you if you're stuck somewhere. They're questions that are asked quite frequently on GitHub and in our discord channel.

Q: How to get the content of the editor already parsed to HTML?

There's are methods available in remirror/core. prosemirrorNodeToHtml which converts the provided node to a HTML string, and htmlToProsemirrorNode which takes the html string you've provided and converts it into a value that can be used within remirror. Please note this does not sanitize the HTML, if you would like to sanitize your html then consider using a library like xss.

To get the html string from the editor the following should work well for you.

import { prosemirrorNodeToHtml } from 'remirror';

const htmlString = prosemirrorNodeToHtml(state.doc);

To convert a html string to a valid node, the following should work.

import { htmlToProsemirrorNode } from 'remirror';

const doc = htmlToProsemirrorNode({ content: html, schema: state.schema });

Q: How to replace the content in the editor?

When replacing the content of the editor, you need to decide if you want to preserve or clear the history. Preserving the history means that users can undo the change (e.g. Ctrl+Z) and get back to the old state.

Preserve history

Calling setContent(...) replaced the content and preserves the history:

Source code
import React from 'react';
import { Remirror, ThemeProvider, useRemirror, useRemirrorContext } from '@remirror/react';

const DOC = {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Undo via Ctrl+Z will restore old content',
},
],
},
],
};

function SetContentButton() {
const { setContent } = useRemirrorContext();
return (
<button onMouseDown={(event) => event.preventDefault()} onClick={() => setContent(DOC)}>
Replace content
</button>
);
}

const ReplaceContentPreserveHistory = (): JSX.Element => {
const { manager, state, onChange } = useRemirror({
extensions: () => [],
content: '<p>Original content</p>',
stringHandler: 'html',
});

return (
<ThemeProvider>
<Remirror manager={manager} state={state} onChange={onChange} autoRender='end'>
<SetContentButton />
</Remirror>
</ThemeProvider>
);
};

export default ReplaceContentPreserveHistory;

Clear history

Calling manager.view.updateState(...) replaces the complete editor state, including the history:

Source code
import React, { useCallback } from 'react';
import { Remirror, ThemeProvider, useRemirror } from '@remirror/react';

const DOC = {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: `Undo via Ctrl+Z won't restore old content`,
},
],
},
],
};

const ReplaceContentAndClearHistory = (): JSX.Element => {
const { manager, state, onChange } = useRemirror({
extensions: () => [],
content: '<p>Original content</p>',
stringHandler: 'html',
});

const handleClick = useCallback(() => {
// Clear out old state when setting data from outside
// This prevents e.g. the user from using CTRL-Z to go back to the old state
manager.view.updateState(manager.createState({ content: DOC }));
}, [manager]);

return (
<ThemeProvider>
<Remirror manager={manager} state={state} onChange={onChange} autoRender='end'>
<button onMouseDown={(event) => event.preventDefault()} onClick={handleClick}>
Replace content
</button>
</Remirror>
</ThemeProvider>
);
};

export default ReplaceContentAndClearHistory;

Outside editor context

Use an imperative handle if you want to replace the content from outside the editor context:

Source code
import React, { forwardRef, Ref, useImperativeHandle, useRef } from 'react';
import { Remirror, ThemeProvider, useRemirror, useRemirrorContext } from '@remirror/react';

const DOC = {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'New content',
},
],
},
],
};

export interface EditorRef {
setContent: (content: any) => void;
}

const ImperativeHandle = forwardRef((_: unknown, ref: Ref<EditorRef>) => {
const { setContent } = useRemirrorContext({
autoUpdate: true,
});

// Expose content handling to outside
useImperativeHandle(ref, () => ({ setContent }));

return <></>;
});

const ReplaceContentImperative = (): JSX.Element => {
const editorRef = useRef<EditorRef | null>(null);
const { manager, state } = useRemirror({
extensions: () => [],
content: '<p>[Replace] button is placed outside the editor (see code)</p>',
stringHandler: 'html',
});

return (
<>
<button
onMouseDown={(event) => event.preventDefault()}
onClick={() => editorRef.current!.setContent(DOC)}
>
Replace content
</button>
<ThemeProvider>
<Remirror manager={manager} initialContent={state} autoRender='end'>
<ImperativeHandle ref={editorRef} />
</Remirror>
</ThemeProvider>
</>
);
};

export default ReplaceContentImperative;