Skip to main content

Creating a React Plugin

In addition to using the Lexical React plugins offered by the core library, you can make your own plugins to extend or alter Lexical's functionality to suit your own use cases.

Lexical's React plugin interface is simple - just create a React component and add it as a child of your LexicalComposer component:

 <LexicalComposer>
<MyLexicalPlugin>
</LexicalComposer>

If the Plugin introduces new nodes, they have to be registered in initialConfig.nodes:

const initialConfig = {
namespace: 'MyEditor',
nodes: [MyLexicalNode],
};
 <LexicalComposer initialConfig={initialConfig}>
<MyLexicalPlugin>
</LexicalComposer>

LexicalComposer provides access to the underlying LexicalEditor instance via React Context:

//MyLexicalPlugin.js

export function MyLexicalPlugin(props) {
const [editor] = useLexicalComposerContext();
...
}

With access to the Editor, your plugin can extend Lexical via Commands, Transforms, or other APIs. For example, the TwitterPlugin embeds a tweet into the editor, fetching the data asynchronously from Twitter based on the provided Tweet ID:

export const INSERT_TWEET_COMMAND: LexicalCommand<string> = createCommand();

export default function TwitterPlugin(): JSX.Element | null {
const [editor] = useLexicalComposerContext();

useEffect(() => {
if (!editor.hasNodes([TweetNode])) {
throw new Error('TwitterPlugin: TweetNode not registered on editor (initialConfig.nodes)');
}

return editor.registerCommand<string>(
INSERT_TWEET_COMMAND,
(payload) => {
const tweetNode = $createTweetNode(payload);
$insertNodeToNearestRoot(tweetNode);

return true;
},
COMMAND_PRIORITY_EDITOR,
);
}, [editor]);

return null;
}

TwitterPlugin is just a React component that accesses the Lexical editor via React Context (useLexicalComposerContext). Using the LexicalEditor instance, this plugin does two things:

  1. Verifies that there is a TweetNode registered on the editor (if you forget to register the node, you can't do #2)
  2. registers a "command", passing a callback that will run when that command is dispatched. The command callback creates and inserts a TweetNode in the editor.

You can see how it's used in the playground here. It's added it as a child of a LexicalComposer component, which does the job of providing the Context necessary for access to the editor instance. To actually trigger this command callback and insert a TweetNode, we have a button that "dispatches" the Tweet command we registered in the plugin.

While the TwitterPlugin registers a command that inserts a custom node, this is only one example of what can be done with a plugin. To get a better idea of what's possible, take a look at the plugins defined in the playground.