Plate.js Rich Text Editor Framework
Plate.js is a comprehensive framework for building rich text editors on the web, leveraging the power and flexibility of Slate.js. It provides a highly extensible, plugin-based architecture that simplifies the development of complex editor features, from basic formatting to advanced elements like tables, images, and AI integrations. The current stable version is 52.3.21, with frequent patch releases (often daily) indicating active development. Plate.js differentiates itself through its extensive collection of pre-built plugins, robust TypeScript support, and a focus on abstracting away much of the underlying Slate complexity, allowing developers to quickly assemble sophisticated editor experiences without deep knowledge of Slate's internal workings. It aims to reduce boilerplate and offer a batteries-included approach for common rich text editor functionalities.
Common errors
-
Error: `editor` object is not defined in the context. Make sure you are rendering `Plate`.
cause Attempting to use Plate hooks (e.g., `useEditorRef`, `usePlateEditor`) outside of a `<Plate>` component's render tree, or before the `editor` prop is passed to `<Plate>`.fixEnsure that any component using Plate-specific hooks is a child of a `<Plate>` component and that the `editor` prop is correctly provided to `<Plate>`. -
Cannot read properties of undefined (reading 'children')
cause This is a common Slate error indicating that the editor's `value` (the document state) is malformed, specifically, a node is missing its `children` array or `text` property, or a block node is directly followed by a text node without an intervening inline node.fixValidate your `initialValue` and any programmatically inserted nodes against Slate's schema. Ensure all nodes have the correct structure: text nodes must have a `text` property, and element nodes must have a `children` array. -
Invariant Violation: Minified React error #XXX; visit https://reactjs.org/docs/error-decoder.html?invariant=XXX for the full message.
cause Mismatch between React versions required by Plate.js (and its peer dependencies) and the React version installed in your project.fixVerify that your `react` and `react-dom` versions satisfy Plate.js's peer dependency requirements (e.g., `>=18.0.0` for recent Plate versions). Use `npm ls react` or `yarn why react` to inspect your dependency tree.
Warnings
- breaking Plate.js is built on Slate.js, which has a rapidly evolving API. Major version updates (e.g., Slate v0.50 to v0.60, or v0.80 to v0.90) often introduce significant breaking changes in Slate's core data model, API, and internal architecture. Plate.js generally follows Slate's versioning closely, meaning upgrades can require substantial code refactoring.
- gotcha Performance can degrade significantly with very large documents or complex nested structures due to the nature of `contentEditable` and the extensive DOM manipulation required. Deeply nested components or custom renderers that re-render frequently can exacerbate this.
- breaking Prior to Plate.js v15 (which aligned with Slate 0.90+), the plugin structure and editor initialization patterns differed significantly. Direct manipulation of the Slate editor object (`editor`) was more common, whereas newer versions emphasize a more declarative, plugin-driven approach.
- gotcha Integrating custom plugins or complex features that heavily rely on direct Slate API interaction can be challenging. Plate.js aims to abstract Slate, but sometimes direct Slate knowledge is needed, potentially leading to conflicts with Plate's abstractions.
Install
-
npm install platejs -
yarn add platejs -
pnpm add platejs
Imports
- Plate
import Plate from 'platejs'; // CommonJS default import is often wrong for modern libs
import { Plate } from '@platejs/react'; - createPlateEditor
import { createPlateEditor } from 'platejs';import { createPlateEditor } from '@platejs/core'; - createParagraphPlugin
import { createParagraphPlugin } from 'platejs/plugins';import { createParagraphPlugin } from '@platejs/paragraph'; - useEditorRef
import { useEditorRef } from '@platejs/core';import { useEditorRef } from '@platejs/react';
Quickstart
import React, { useMemo } from 'react';
import { createPlateEditor } from '@platejs/core';
import { Plate, usePlateEditorRef, PlateContent } from '@platejs/react';
import { createParagraphPlugin } from '@platejs/paragraph';
import { createBasicElementsPlugin } from '@platejs/elements';
import { createAlignPlugin } from '@platejs/alignment';
import { createBoldPlugin, createItalicPlugin } from '@platejs/basic-marks';
const initialValue = [
{ type: 'p', children: [{ text: 'Hello, Plate.js!' }] },
{ type: 'p', children: [{ text: 'Start typing here...' }] },
];
function MyEditor() {
const plugins = useMemo(
() => [
createParagraphPlugin(),
createBasicElementsPlugin(),
createAlignPlugin({ options: { align: 'left' } }),
createBoldPlugin(),
createItalicPlugin(),
],
[]
);
const editor = useMemo(() => createPlateEditor(), []);
return (
<Plate editor={editor} plugins={plugins} initialValue={initialValue}>
<PlateContent
className="p-4 min-h-[200px] border border-gray-300 rounded-md"
placeholder="Type something..."
/>
</Plate>
);
}
export default MyEditor;