Skip to main content
Lexical provides several React hooks for accessing editor state and functionality within components.

Context Hooks

useLexicalComposerContext

Access the editor instance and context from within a LexicalComposer.
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';

function MyComponent() {
  const [editor, context] = useLexicalComposerContext();

  // Use editor methods
  editor.update(() => {
    // Modify editor state
  });

  // Access theme
  const theme = context.getTheme();

  return <div>...</div>;
}
Returns: [LexicalEditor, LexicalComposerContextType]
  • First element: The LexicalEditor instance
  • Second element: Context object with getTheme() method
Throws: Error if called outside of a LexicalComposer or LexicalNestedComposer

State Observation Hooks

useLexicalEditable

Subscribe to the editor’s editable state.
import { useLexicalEditable } from '@lexical/react/useLexicalEditable';

function ToolbarButton() {
  const isEditable = useLexicalEditable();

  return (
    <button disabled={!isEditable}>
      Format
    </button>
  );
}
Returns: boolean - Current editable state of the editor This hook properly handles React StrictMode and concurrency, making it safer than manually using editor.registerEditableListener().

useLexicalIsTextContentEmpty

Check if the editor’s text content is empty.
import { useLexicalIsTextContentEmpty } from '@lexical/react/useLexicalIsTextContentEmpty';

function CharacterCount() {
  const [editor] = useLexicalComposerContext();
  const isEmpty = useLexicalIsTextContentEmpty(editor, true);

  return <div>{isEmpty ? 'Empty' : 'Has content'}</div>;
}
Parameters:
editor
LexicalEditor
required
The editor instance to observe.
trim
boolean
If true, whitespace-only content is considered empty.
Returns: boolean - Whether the editor’s text content is empty

useLexicalSubscription

Generic hook for subscribing to Lexical editor values for render.
import { useLexicalSubscription } from '@lexical/react/useLexicalSubscription';
import type { LexicalSubscription } from '@lexical/react/useLexicalSubscription';

function useMyCustomState(): MyState {
  const subscription = useCallback((editor: LexicalEditor): LexicalSubscription<MyState> => {
    return {
      initialValueFn: () => editor.getEditorState().read(() => {
        // Return initial value
        return computeState();
      }),
      subscribe: (callback) => {
        return editor.registerUpdateListener(() => {
          const newValue = editor.getEditorState().read(() => {
            return computeState();
          });
          callback(newValue);
        });
      },
    };
  }, []);

  return useLexicalSubscription(subscription);
}
Parameters:
subscription
(editor: LexicalEditor) => LexicalSubscription<T>
required
Function that creates a subscription object. Must have a stable identity (use useCallback or define at module scope).
Returns: T - The current value from the subscription The subscription object must provide:
  • initialValueFn: () => T - Function to compute the initial value
  • subscribe: (callback: (value: T) => void) => () => void - Function to register updates and return cleanup

Selection and Node Hooks

useLexicalNodeSelection

Manage selection state for a specific node (useful for decorators and custom nodes).
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';

function ImageComponent({ nodeKey }) {
  const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);

  return (
    <div
      className={isSelected ? 'selected' : ''}
      onClick={() => setSelected(true)}
    >
      <img src="..." />
    </div>
  );
}
Parameters:
key
NodeKey
required
The node key to track selection for.
Returns: [boolean, (selected: boolean) => void, () => void]
  • isSelected (boolean): Whether the node is currently selected
  • setSelected (function): Set the selection state of the node
    • Parameters: selected: boolean - true to select, false to deselect
  • clearSelection (function): Clear the node selection

useLexicalTextEntity

Register text entity transformations (e.g., mentions, hashtags, custom tokens).
import { useLexicalTextEntity } from '@lexical/react/useLexicalTextEntity';
import { MentionNode } from './nodes/MentionNode';

function MentionPlugin() {
  const createMentionNode = useCallback((textNode) => {
    return new MentionNode(textNode.getTextContent());
  }, []);

  const getMentionMatch = useCallback((text) => {
    const match = /@[\w]+/.exec(text);
    if (match) {
      return {
        end: match.index + match[0].length,
        start: match.index,
      };
    }
    return null;
  }, []);

  useLexicalTextEntity(
    getMentionMatch,
    MentionNode,
    createMentionNode
  );

  return null;
}
Parameters:
getMatch
(text: string) => EntityMatch | null
required
Function to find entity matches in text. Returns an object with start and end indices, or null.
targetNode
Klass<T extends TextNode>
required
The node class to create for matched entities.
createNode
(textNode: TextNode) => T
required
Factory function to create the entity node from a text node.
Returns: void

Type Definitions

LexicalSubscription

type LexicalSubscription<T> = {
  initialValueFn: () => T;
  subscribe: (callback: (value: T) => void) => () => void;
};
Object describing how to subscribe to a value in the editor.
initialValueFn
() => T
required
Function that returns the initial value. Called during render.
subscribe
(callback: (value: T) => void) => () => void
required
Function that registers a callback for updates. Returns a cleanup function.

EntityMatch

type EntityMatch = {
  start: number;
  end: number;
};
Describes the position of a text entity match.
start
number
required
Starting index of the match in the text.
end
number
required
Ending index of the match in the text.

Build docs developers (and LLMs) love