Controlled Editor Value

How to control the editor value.

Implementing a fully controlled editor value in Plate (and Slate) is complex due to several factors:

  1. The editor state includes more than just the content (editor.children). It also includes editor.selection and editor.history.

  2. Directly replacing editor.children can break the selection and history, leading to unexpected behavior or crashes.

  3. All changes to the editor's value should ideally happen through Transforms to maintain consistency with selection and history.

Given these challenges, it's generally recommended to use Plate as an uncontrolled input. However, if you need to make external changes to the editor's content, you can use editor.tf.setValue(value) function.

Alternatively, you can use editor.tf.reset() to reset the editor state, which will reset the selection and history.

function App() {
  const editor = usePlateEditor({
    value: 'Initial Value',
    // Disable the editor if initial value is not yet ready
    // enabled: !!value,
  });
 
  return (
    <div>
      <Plate editor={editor}>
        <PlateContent />
      </Plate>
 
      <button
        onClick={() => {
          // Replace with HTML string
          editor.tf.setValue('Replaced Value');
 
          // Replace with JSON value
          editor.tf.setValue([
            {
              type: 'p',
              children: [{ text: 'Replaced Value' }],
            },
          ]);
 
          // Replace with empty value
          editor.tf.setValue();
        }}
      >
        Replace Value
      </button>
      
      <button
        onClick={() => {
          editor.tf.reset();
        }}
      >
        Reset Editor
      </button>
    </div>
  );
}
Loading...
components/controlled-demo.tsx
'use client';

import React from 'react';

import {
  Plate,
  focusEditor,
  focusEditorEdge,
  usePlateEditor,
} from '@udecode/plate-common/react';

import { Button } from '@/components/plate-ui/button';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';

export default function ControlledEditorDemo() {
  const editor = usePlateEditor({
    value: [
      {
        children: [{ text: 'Initial Value' }],
        type: 'p',
      },
    ],
  });

  return (
    <div>
      <Plate editor={editor}>
        <EditorContainer>
          <Editor />
        </EditorContainer>
      </Plate>

      <div className="mt-4 flex flex-col gap-2">
        <Button
          onClick={() => {
            // Replace with HTML string
            editor.tf.setValue([
              {
                children: [{ text: 'Replaced Value' }],
                type: 'p',
              },
            ]);

            focusEditorEdge(editor, { edge: 'end' });
          }}
        >
          Replace Value
        </Button>

        <Button
          onClick={() => {
            editor.tf.reset();

            focusEditor(editor);
          }}
        >
          Reset Editor
        </Button>
      </div>
    </div>
  );
}