Import Plate state hooks from platejs/react. Use editor hooks for document
state, usePluginStore for plugin state, and event hooks for focus history.
Render editor hooks below EditorRoot, or below a EditorController
that connects shared UI to its editors.
| Hook | Returns |
|---|---|
useEditor() | The matching editor; throws when no editor is active. |
useOptionalEditor() |
The matching editor, or null while its controller has no matching editor. |
useEditorId() | The resolved editor's ID. |
useEditorMounted() | Whether the editor's editable surface is mounted. |
useEditorSelection() | The current selected-root range, or null. |
useEditorHasSelection() | Whether a selected-root text selection exists, including a caret. Rerenders only when presence changes. |
useEditorValue() | The current selected-root children. |
useEditorState(selector, options?) | A subscribed value derived from immutable editor state. |
Hooks use the editor selected by the nearest EditorContent, EditorRoot, EditorController, or EditorProvider. useOptionalEditor() returns null without a provider or selected editor. Application IDs do not route mounted views.
import { useEditorMounted, useEditorValue } from 'platejs/react';
export function EditorStatus() {
const mounted = useEditorMounted();
const value = useEditorValue();
return <p>{mounted ? `${value.length} top-level nodes` : 'Loading editor…'}</p>;
}import { useEditorMounted, useEditorValue } from 'platejs/react';
export function EditorStatus() {
const mounted = useEditorMounted();
const value = useEditorValue();
return <p>{mounted ? `${value.length} top-level nodes` : 'Loading editor…'}</p>;
}useEditorContainerRef() returns the matching EditorContainer ref. Its
current value is null before mount and after unmount. Use it to anchor
editor UI to its container; it does not identify the editable DOM element.
EditorRoot and EditorContent manage editor registration and mount status. Set
primary-editor eligibility through EditorRoot's primary prop and pass read-only
state through their readOnly props.
Plugin state belongs to an installed descriptor and its editor. Let the descriptor infer the state keys and selector result.
import { definePlugin, usePluginStore } from 'platejs/react';
export const PanelPlugin = definePlugin('panel', {
initialState: { open: false },
});
export function PanelStatus() {
const open = usePluginStore(PanelPlugin, 'open');
return <p>{open ? 'Panel open' : 'Panel closed'}</p>;
}import { definePlugin, usePluginStore } from 'platejs/react';
export const PanelPlugin = definePlugin('panel', {
initialState: { open: false },
});
export function PanelStatus() {
const open = usePluginStore(PanelPlugin, 'open');
return <p>{open ? 'Panel open' : 'Panel closed'}</p>;
}Include PanelPlugin in the editor's plugins array. Use
usePluginStore(PanelPlugin, (state) => state.open) for a selector callback.
useEditor().plugin(PanelPlugin) returns the descriptor's inferred portal for API
calls; it does not subscribe to plugin state. Outside React rendering,
editor.plugin(PanelPlugin).store.get('open') reads the current value.
useEditorFocused() reads whether the current editable has focus.
useFocusedLast() reads whether the provider's editor was last focused in its
owning document. It stays true while a toolbar input has focus and becomes
false when another editor in that document receives focus or the focused view
unmounts. Editors in separate documents keep independent focus history, and
matching editor IDs do not make their instances equivalent.
import { useFocusedLast } from 'platejs/react';
export function EditorTools() {
const focusedLast = useFocusedLast();
return <div hidden={!focusedLast}>Editor tools</div>;
}import { useFocusedLast } from 'platejs/react';
export function EditorTools() {
const focusedLast = useFocusedLast();
return <div hidden={!focusedLast}>Editor tools</div>;
}Render this hook under EditorRoot, or under EditorController with an active editor.
Use useOptionalEditor() to guard a child containing strict editor hooks while
an empty controller has no editor. State, value and selection hooks require an
active editor.
Use <EditorProvider editor={editor}> to bind UI to an existing editor; editor={null} represents no target. This provider creates no document, history, or editable view. To retain a concrete editor type in selectors, use useEditorRuntimeState(editor, selector), useEditorViewState(editor, selector), or useEditorPluginStore(editor, Plugin, selector).
useEditorReadOnly() reads the selected view’s current permission. A captured view rejects writes after unmount. Views of one model share document content, plugin stores, and undo history.