Get up and running with Lexical quickly. This guide will walk you through creating your first text editor.
Installation
Install Lexical packages
Install the core Lexical package and React bindings:npm install lexical @lexical/react
Create your editor component
Import the necessary components and create a basic editor.
Add plugins
Enhance your editor with plugins for history, error handling, and more.
Plain Text Editor
Here’s a minimal plain text editor:
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
const initialConfig = {
namespace: 'MyEditor',
onError: (error: Error) => console.error(error),
};
export default function Editor() {
return (
<LexicalComposer initialConfig={initialConfig}>
<PlainTextPlugin
contentEditable={<ContentEditable />}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
</LexicalComposer>
);
}
Rich Text Editor
For a rich text editor with formatting capabilities:
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
import { HeadingNode, QuoteNode } from '@lexical/rich-text';
import { ListNode, ListItemNode } from '@lexical/list';
import { LinkNode } from '@lexical/link';
const initialConfig = {
namespace: 'RichEditor',
nodes: [HeadingNode, QuoteNode, ListNode, ListItemNode, LinkNode],
onError: (error: Error) => console.error(error),
};
export default function RichEditor() {
return (
<LexicalComposer initialConfig={initialConfig}>
<RichTextPlugin
contentEditable={<ContentEditable />}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
</LexicalComposer>
);
}
Vanilla JavaScript
You can also use Lexical without React:
import { createEditor } from 'lexical';
import { $getRoot, $createParagraphNode, $createTextNode } from 'lexical';
const editorElement = document.getElementById('editor');
const editor = createEditor({
namespace: 'MyEditor',
onError: (error) => console.error(error),
});
editor.setRootElement(editorElement);
// Initialize with content
editor.update(() => {
const root = $getRoot();
const paragraph = $createParagraphNode();
const text = $createTextNode('Hello, Lexical!');
paragraph.append(text);
root.append(paragraph);
});
Reading and Updating State
Reading State
Use editor.read() to safely read the editor state:
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $getRoot, $getSelection } from 'lexical';
import { useEffect } from 'react';
function MyPlugin() {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerUpdateListener(({ editorState }) => {
editorState.read(() => {
const root = $getRoot();
const selection = $getSelection();
console.log('Root:', root);
console.log('Selection:', selection);
});
});
}, [editor]);
return null;
}
Updating State
Use editor.update() to make changes:
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $getRoot, $createParagraphNode, $createTextNode } from 'lexical';
function MyPlugin() {
const [editor] = useLexicalComposerContext();
const insertText = () => {
editor.update(() => {
const root = $getRoot();
const paragraph = $createParagraphNode();
const text = $createTextNode('Hello, Lexical!');
paragraph.append(text);
root.append(paragraph);
});
};
return <button onClick={insertText}>Insert Text</button>;
}
Functions prefixed with $ (like $getRoot(), $createTextNode()) can only be called within editor.update() or editor.read() blocks.
Styling
Add CSS to style your editor:
.editor-container {
margin: 20px auto;
max-width: 800px;
border: 1px solid #ddd;
border-radius: 8px;
}
.editor-input {
min-height: 200px;
padding: 10px;
font-size: 16px;
outline: none;
}
Next Steps
Core Concepts
Understand Lexical’s architecture and design
React Plugins
Explore available plugins for lists, tables, links, and more
Create Custom Nodes
Learn how to create custom node types
Working with Commands
Implement custom commands and event handling