# Integrating CKEditor 5 with React multi-root editor hook from CDN

You can add the CKEditor 5 multi-root editor to a React application using the `useMultiRootEditor` hook from the official CKEditor 5 React integration. A multi-root editor has several separate editable areas (roots) that form a single document while sharing one toolbar, configuration, and undo stack. The hook returns the toolbar and editable elements to render, along with the editor instance and its data. For other editor types, see the [default React integration](react-default-cdn.md).

> **Note**
>
> The multi-root editors in React are supported since version 6.2.0 of this package.
>
> Unlike the [default integration](react-default-cdn.md), we prepared the multi-root editor integration based on the hooks and new React mechanisms.

<a id="quick-start">

## Quick start

This guide assumes you already have a React project. If you want to create a new one, you can use the [Vite](https://vitejs.dev/guide/) CLI. It allows you to create and customize your project with templates. For example, you can set up your project with TypeScript support.

> **Note**
>
> To use our Cloud CDN services, [create a free account](https://portal.ckeditor.com/checkout?plan=free). Learn more about [license key activation](../../../licensing/license-key-and-activation.md).

Install the [CKEditor 5 WYSIWYG editor package for React](https://www.npmjs.com/package/@ckeditor/ckeditor5-react) and the [multi-root editor type](../../../setup/editor-types.md#multi-root-editor).

```bash
npm install ckeditor5 @ckeditor/ckeditor5-react
```

Use the `useMultiRootEditor` hook inside your project:

```jsx
import React from "react";
import { useMultiRootEditor, withCKEditorCloud } from "@ckeditor/ckeditor5-react";

const withCKCloud = withCKEditorCloud( {
	cloud: {
		version: "48.5.2",
		languages: [ "es" ],
		premium: true,
	},

	// Optional:
	renderError: ( error ) => <div>Error!</div>,

	// Optional:
	renderLoader: () => <div>Loading...</div>,
} );

const MultiRootEditorDemo = withCKCloud(
	( { data, cloud } ) => {
		const {
			MultiRootEditor: MultiRootEditorBase,
			Essentials,
			Paragraph
			Bold,
			Italic
		} = cloud.CKEditor;

		const { FormatPainter } = cloud.CKEditorPremiumFeatures;

		class MultiRootEditor extends MultiRootEditorBase {
			static builtinPlugins = [
				Essentials,
				Paragraph,
				Bold,
				Italic,
				FormatPainter
			];

			static defaultConfig = {
				toolbar: [ 'undo', 'redo', '|', 'bold', 'italic', '|', 'formatPainter' ]
			};
		}

		const { toolbarElement, editableElements } = useMultiRootEditor( {
			editor: MultiRootEditor,
			data,
		} );

		return (
			<div>
				{ toolbarElement }
				{ editableElements }
			</div>
		);
	}
);
```

<a id="hook-properties">

## Hook properties

The `useMultiRootEditor` hook supports the following properties:

* `editor: MultiRootEditor` (required) – The [`MultiRootEditor`](../../../../api/module_editor-multi-root_multirooteditor-MultiRootEditor.md) constructor to use.

* `data: Object` – The initial data for the created editor. See the [Getting and setting data](../../../setup/getting-and-setting-data.md) guide.

* `rootsAttributes: Object` – The initial roots attributes for the created editor.

* `config: Object` – The editor configuration. See the [Configuration](../../../setup/configuration.md) guide.

* `disabled: Boolean` – The [`MultiRootEditor`](../../../../api/module_editor-multi-root_multirooteditor-MultiRootEditor.md) is being switched to read-only mode if the property is set to `true`.

* `disableWatchdog: Boolean` – If set to `true`, [the watchdog feature](../../../../features/watchdog.md) will be disabled. It is set to `false` by default.

* `watchdogConfig: WatchdogConfig` – [Configuration object](../../../../api/module_watchdog_watchdog-WatchdogConfig.md) for the [watchdog feature](../../../../features/watchdog.md).

* `isLayoutReady: Boolean` – A property that delays the editor creation when set to `false`. It starts the initialization of the multi-root editor when sets to `true`. Useful when the CKEditor 5 annotations or a presence list are used.

* `disableTwoWayDataBinding: Boolean` – Allows disabling the two-way data binding mechanism between the editor state and `data` object to improve editor efficiency. The default value is `false`.

* `onReady: Function` – It is called when the editor is ready with a [`MultiRootEditor`](../../../../api/module_editor-multi-root_multirooteditor-MultiRootEditor.md) instance. This callback is also called after the reinitialization of the component if an error occurred.

* `onChange: Function` – It is called when the editor data has changed. See the [`editor.model.document#change:data`](../../../../api/module_engine_model_document-ModelDocument.md#event-change:data) event.

* `onBlur: Function` – It is called when the editor was blurred. See the [`editor.editing.view.document#blur`](../../../../api/module_engine_view_document-ViewDocument.md#event-blur) event.

* `onFocus: Function` – It is called when the editor was focused. See the [`editor.editing.view.document#focus`](../../../../api/module_engine_view_document-ViewDocument.md#event-focus) event.

* `onError: Function` – It is called when the editor has crashed during the initialization or during the runtime. It receives two arguments: the error instance and the error details.\
  Error details is an object that contains two properties:

  * `phase: 'initialization'|'runtime'` – Informs when an error has occurred (during the editor or context initialization, or after the initialization).
  * `willEditorRestart: Boolean` – If set to `true`, the editor component will restart itself.

The editor event callbacks (`onChange`, `onBlur`, `onFocus`) receive two arguments:

1. An [`EventInfo`](../../../../api/module_utils_eventinfo-EventInfo.md) object.
2. An [`MultiRootEditor`](../../../../api/module_editor-multi-root_multirooteditor-MultiRootEditor.md) instance.

<a id="hook-values">

## Hook values

The `useMultiRootEditor` hook returns the following values:

* `editor` – The instance of created editor.
* `toolbarElement` – `ReactElement` that contains the toolbar. It could be rendered anywhere in the application.
* `editableElements` – An array of `ReactElements` that describes the editor’s roots. This array is updated after detaching an existing root or adding a new root.
* `data` – The current state of the editor’s data. It is updated after each editor update. Note that you should not use it if you disabled two-way binding by passing the `disableTwoWayDataBinding` property.
* `setData` – The function used for updating the editor’s data.
* `attributes` – The current state of the editor’s attributes. It is updated after each editor attributes update. Note that you should not use it if you disabled two-way binding by passing the `disableTwoWayDataBinding` property.
* `setAttributes` – The function used for updating the editor’s attributes.
* `addRoot` – A function that adds a new root to the editor at runtime. It accepts a single options object with `name`, `data`, `attributes`, `modelElement` (for example, `'$inlineRoot'`), and `editableOptions` (per-root `element`, `placeholder`, and `label`). The returned promise resolves once the root has been added.
* `removeRoot` – A function that detaches a root from the editor by name. The returned promise resolves once the root has been removed.

<a id="context-feature">

## Context feature

The `useMultiRootEditor` hook also supports the [context feature](../../../../features/collaboration/context-and-collaboration-features.md), as described in the main [React integration](react-default-cdn.md#context-feature) guide.

However, as the multi-root editor addresses most use cases of the context feature, consider if you need to employ it.

<a id="two-way-data-binding">

## Two-way data binding

By default, the two-way data binding is enabled. It means that every change done in the editor is automatically applied in the `data` object returned from the `useMultiRootEditor` hook. Additionally, if you want to change or set data in the editor, you can simply use `setData` method provided by the hook. It works the same way in case of attributes – the hook provides the `attributes` object and the `setAttributes` method to update them. It ensures that if you want to use or save the state of the editor, these objects are always up-to-date.

> **Note**
>
> Two-way data binding may lead to performance issues with large editor content. In such cases, it is recommended to disable it by setting the `disableTwoWayDataBinding` property to `true` when using the `useMultiRootEditor` hook. When this is disabled, you will need to handle data synchronization manually if it is needed.
>
> The recommended approach for achieving this is based on utilizing the [autosave plugin](../../../../features/autosave.md). The second approach involves providing the `onChange` callback, which is called on each editor update.

<a id="how-to">

## How to?

<a id="adding-and-removing-roots-dynamically">

### Adding and removing roots dynamically

The hook exposes `addRoot` and `removeRoot` helpers so you can manage roots from event handlers or effects. The `addRoot` helper accepts the new root’s name, initial data, optional attributes, an optional `modelElement` for the schema, and `editableOptions` describing the editable element (its host tag, placeholder text, and accessible label).

```tsx
const { addRoot, removeRoot } = useMultiRootEditor( editorProps );

// Add a block-content root rendered as a <section>.
await addRoot( {
	name: 'sidebar',
	data: '<p>Sidebar content</p>',
	attributes: { order: 30 },
	editableOptions: {
		element: 'section',
		placeholder: 'Type the sidebar content...',
		label: 'Sidebar'
	}
} );

// Later, remove the same root.
await removeRoot( 'sidebar' );
```

The `editableOptions.element` field accepts a tag name string (`'section'`, `'article'`) or a descriptor object with `name`, `classes`, `styles`, and `attributes`.

<a id="mixing-standard-and-inline-roots">

### Mixing standard and inline roots

A multi-root editor can host both standard and inline roots in the same document. Set `modelElement` to `'$inlineRoot'` for any root that should accept only inline content (text, bold, italic, links) instead of blocks. This is useful for titles, captions, or single-line fields combined with a block-based body.

```tsx
await addRoot( {
	name: 'title',
	data: 'Document title',
	modelElement: '$inlineRoot',
	editableOptions: {
		element: 'h1',
		placeholder: 'Enter title...'
	}
} );
```

Without `modelElement: '$inlineRoot'`, only the host tag changes – the schema still permits blocks inside the root.

<a id="contributing-and-reporting-issues">

## Contributing and reporting issues

The source code of rich text editor component for React is available on GitHub in <https://github.com/ckeditor/ckeditor5-react>.

<a id="next-steps">

## Next steps

* See how to manipulate the editor’s data in the [Getting and setting data](../../../setup/getting-and-setting-data.md) guide.
* Refer to further guides in the [setup section](../../../setup/configuration.md) to see how to customize your editor further.
* Check the [features category](../../../../features/index.md) to learn more about individual features.

---

Full index of the CKEditor 5 documentation: [llms.txt](../../../../../llms.txt)
