Editor Methods
Explore the various methods available for interacting with and customizing the Plate editor.
This guide covers the various methods available on the Plate editor instance.
Accessing the Editor
How you access the editor instance depends on the context in which you need it.
Below Plate
Use one of these hooks:
useEditorRef
: Never re-render.useEditorSelector
: Re-render only when a specific editor property changes.useEditorState
: Re-render on every change.
import { useEditorRef, useEditorSelector, useEditorState } from '@udecode/plate-common/react';
const MyComponent = () => {
const editor = useEditorRef();
const hasSelection = useEditorSelector((editor) => !!editor.selection, []);
const editorState = useEditorState();
// ...
};
useEditorRef
- Use a reference to editor that never gets replaced. This should be the default choice.
- Since editor is a mutable object that gets updated by reference,
useEditorRef
is always sufficient for accessing the editor inside callbacks. useEditorRef
will never cause your component to re-render, so it's the best choice for performance.
useEditorSelector
- Subscribe to a specific selector based on editor. This is the most performant option for subscribing to state changes.
- Example usage:
const hasSelection = useEditorSelector((editor) => !!editor.selection, []);
- When you want your component to re-render in response to a specific change that you're interested in, you can use
useEditorSelector
to access the relevant property. - The selector function is called every time the editor changes (i.e. on every keystroke or selection change), but the component only re-renders when the return value changes.
- For this to work properly, you should make sure that the return value can be compared using
===
. In most cases, this means returning a primitive value, like a number, string or boolean. - You can provide a custom
equalityFn
in the options touseEditorSelector
for cases where===
isn't sufficient. - If the selector function depends on any locally scoped variables, you should include these in the dependency list.
useEditorState
- Re-render every time the editor changes.
- Using
useEditorState
will cause your component to re-render every time the user presses a key or changes the selection. - This may cause performance issues for large documents, or when re-rendering is particularly expensive.
Outside Plate
To access the editor outside the Plate
component or work with multiple editors, use the PlateController
component:
import { PlateController } from '@udecode/plate-common/react';
const App = () => (
<PlateController>
<Toolbar />
<MyEditor />
</PlateController>
);
const Toolbar = () => {
const editor = useEditorState();
const isMounted = useEditorMounted();
// Use editor methods here
};
PlateController
manages active editors:
- The first mounted editor is active by default (override with
primary={false}
onPlate
). - Focus changes the active editor.
- An editor remains active until another is focused or it unmounts.
Hooks like useEditorRef
and useEditorSelector
work with the active editor inside PlateController
. If no editor is active, they return a fallback editor, which:
- Provides default values for queries.
- Cannot be mutated.
- Throws errors on state-changing operations.
Fallback editor scenarios:
- No mounted
Plate
components. - All
Plate
components are non-primary. - During
PlateContent
mounting.
You can check if any editor is mounted using useEditorMounted
:
const Toolbar = () => {
const editor = useEditorState();
const isMounted = useEditorMounted();
if (!isMounted) {
return <div>Editor not ready</div>;
}
return <div>{/* Toolbar content */}</div>;
};
You can also use editor.isFallback
to check if the editor is a fallback instance.
API Methods
getApi
Retrieve the typed API for the editor:
const api = editor.getApi(TablePlugin);
api.api.create.cell(); // Type-safe API method
getTransforms
Get the typed transforms for the editor:
const tf = editor.getTransforms(TablePlugin);
tf.insert.tableRow(); // Type-safe transform method
Plugin Methods
getPlugin
Retrieve the editor plugin instance by its key or base plugin:
const paragraphPlugin = editor.getPlugin(ParagraphPlugin);
const headingPlugin = editor.getPlugin({ key: 'heading' });
getType
Get the node type associated with a plugin:
const paragraphType = editor.getType(ParagraphPlugin);
Option Methods
getOption
Get a specific option value for a plugin:
const search = editor.getOption(FindReplacePlugin, 'search');
getOptions
Get all options for a plugin:
const linkOptions = editor.getOptions(LinkPlugin);
setOption
Set a specific option value for a plugin:
editor.setOption(FindReplacePlugin, 'search', 'hello');
setOptions
Set multiple options for a plugin:
editor.setOptions(FindReplacePlugin, {
search: 'hello',
caseSensitive: true,
});
You can also use a function to update options using Immer:
editor.setOptions(FindReplacePlugin, (draft) => {
draft.search = 'hello';
draft.caseSensitive = true;
});
getOptionsStore
Get the zustand-x options store for a plugin:
const store = editor.getOptionsStore(FindReplacePlugin);
React Hooks
useOption
Subscribe to a specific option value in a React component:
const MyComponent = () => {
const search = editor.useOption(FindReplacePlugin, 'search');
return <div>Current search: {search}</div>;
};
useOptions
You can also use a selector function to subscribe to specific parts of the options:
const MyComponent = () => {
const search = editor.useOptions(FindReplacePlugin, (options) => options.search);
return <div>Current search: {search}</div>;
};
useOptionsStore
Get the zustand-x store hook for a plugin:
const store = editor.useOptionsStore(FindReplacePlugin);
Plate Store
setPlateState
Update the global Plate state:
editor.setPlateState('readOnly', true);
Customizable and extensible.