Listeners
Listeners are a mechanism that lets the Editor instance inform the user when a certain operation has occured. All listeners follow a reactive pattern where you can do an operation upon something happening in the future. All listeners also return a function that easily allows for the listener to be unregistered. Below are the different listeners that Lexical supports today:
registerUpdateListener
Get notified when Lexical commits an update to the DOM.
const removeUpdateListener = editor.registerUpdateListener(({editorState}) => {
// The latest EditorState can be found as `editorState`.
// To read the contents of the EditorState, use the following API:
editorState.read(() => {
// Just like editor.update(), .read() expects a closure where you can use
// the $ prefixed helper functions.
});
});
// Do not forget to unregister the listener when no longer needed!
removeUpdateListener();
The update listener callbacks receives a single argument containing the follow properties:
editorState
the latest updated Editor StateprevEditorState
the previous Editor Statetags
a Set of all tags that were passed to the update
One thing to be aware of is "waterfall" updates. This is where you might schedule an update inside an update listener, as show below:
editor.registerUpdateListener(({editorState}) => {
// Read the editorState and maybe get some value.
editorState.read(() => {
// ...
});
// Then schedule another update.
editor.update(() => {
// ...
});
});
The problem with this pattern is that it means we end up doing two DOM updates, when we likely could have done it in a single DOM update. This can have an impact on performance, which is important in text editor. To avoid this, we recommend looking into Node Transforms, which allow you to listen to node changes and transform them as part of the same given update, meaning no waterfalls!
registerTextContentListener
Get notified when Lexical commits an update to the DOM and the text content of the editor changes from the previous state of the editor. If the text content is the same between updates, no notifications to the listeners will happen.
const removeTextContentListener = editor.registerTextContentListener(
(textContent) => {
// The latest text content of the editor!
console.log(textContent);
},
);
// Do not forget to unregister the listener when no longer needed!
removeTextContentListener();
registerMutationListener
Get notified when a specific type of Lexical node has been mutated. There are three states of mutation:
created
destroyed
updated
Mutation listeners are great for tracking the lifecycle of specific types of node. They can be used to handle external UI state and UI features relating to specific types of node.
If any existing nodes are in the DOM, and skipInitialization is not true, the listener will be called immediately with an updateTag of 'registerMutationListener' where all nodes have the 'created' NodeMutation. This can be controlled with the skipInitialization option (whose default was previously true for backwards compatibility with <=0.16.1 but has been changed to false as of 0.21.0).
const removeMutationListener = editor.registerMutationListener(
MyCustomNode,
(mutatedNodes, { updateTags, dirtyLeaves, prevEditorState }) => {
// mutatedNodes is a Map where each key is the NodeKey, and the value is the state of mutation.
for (let [nodeKey, mutation] of mutatedNodes) {
console.log(nodeKey, mutation)
}
},
{skipInitialization: false}
);
// Do not forget to unregister the listener when no longer needed!
removeMutationListener();
registerEditableListener
Get notified when the editor's mode has changed. The editor's mode can be changed
via editor.setEditable(boolean)
.
const removeEditableListener = editor.registerEditableListener(
(editable) => {
// The editor's mode is passed in!
console.log(editable);
},
);
// Do not forget to unregister the listener when no longer needed!
removeEditableListener();
registerDecoratorListener
Get notified when the editor's decorator object changes. The decorator object contains
all DecoratorNode
keys -> their decorated value. This is primarily used with external
UI frameworks.
const removeDecoratorListener = editor.registerDecoratorListener(
(decorators) => {
// The editor's decorators object is passed in!
console.log(decorators);
},
);
// Do not forget to unregister the listener when no longer needed!
removeDecoratorListener();
registerRootListener
Get notified when the editor's root DOM element (the content editable Lexical attaches to) changes. This is primarily used to attach event listeners to the root element. The root listener function is executed directly upon registration and then on any subsequent update.
const removeRootListener = editor.registerRootListener(
(rootElement, prevRootElement) => {
//add listeners to the new root element
//remove listeners from the old root element
},
);
// Do not forget to unregister the listener when no longer needed!
removeRootListener();