The CKEditor React component provides comprehensive integration for single-root CKEditor 5 instances with advanced lifecycle management, error handling, and watchdog functionality.
Main React class component for integrating CKEditor 5 in single-root scenarios.
/**
* React class component for CKEditor 5 integration
* Provides comprehensive lifecycle management and error handling
*/
class CKEditor<TEditor extends Editor> extends React.Component<Props<TEditor>> {
/** Access to the watchdog instance managing the editor */
get watchdog(): EditorWatchdog<TEditor> | EditorWatchdogAdapter<TEditor> | null;
/** Access to the current editor instance */
get editor(): Editor | null;
}
interface Props<TEditor extends Editor> {
/** CKEditor constructor and related classes */
editor: {
create(...args: any): Promise<TEditor>;
EditorWatchdog: typeof EditorWatchdog;
ContextWatchdog: typeof ContextWatchdog;
};
/** Editor configuration object */
config?: EditorConfig;
/** Initial content data */
data?: string;
/** Read-only mode toggle */
disabled?: boolean;
/** Watchdog configuration for error recovery */
watchdogConfig?: WatchdogConfig;
/** Disable watchdog functionality */
disableWatchdog?: boolean;
/** Callback fired when editor is ready */
onReady?: (editor: TEditor) => void;
/** Callback fired after editor is destroyed */
onAfterDestroy?: (editor: TEditor) => void;
/** Error handling callback */
onError?: (error: Error, details: ErrorDetails) => void;
/** Content change callback */
onChange?: (event: EventInfo, editor: TEditor) => void;
/** Focus event callback */
onFocus?: (event: EventInfo, editor: TEditor) => void;
/** Blur event callback */
onBlur?: (event: EventInfo, editor: TEditor) => void;
/** Context metadata for shared context scenarios */
contextItemMetadata?: CKEditorConfigContextMetadata;
/** Component identifier for React reconciliation */
id?: any;
}Usage Examples:
import React, { useState } from 'react';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import { ClassicEditor } from 'ckeditor5';
// Basic usage
function BasicEditor() {
const [data, setData] = useState('<p>Initial content</p>');
return (
<CKEditor
editor={ClassicEditor}
data={data}
config={{
toolbar: ['bold', 'italic', 'link']
}}
onChange={(event, editor) => {
setData(editor.getData());
}}
/>
);
}
// Advanced usage with all options
function AdvancedEditor() {
const [data, setData] = useState('');
const [disabled, setDisabled] = useState(false);
return (
<CKEditor
editor={ClassicEditor}
data={data}
disabled={disabled}
config={{
toolbar: ['bold', 'italic', 'link', 'bulletedList', 'numberedList'],
placeholder: 'Start typing...'
}}
watchdogConfig={{
crashNumberLimit: 5
}}
onReady={(editor) => {
console.log('Editor ready:', editor);
}}
onChange={(event, editor) => {
setData(editor.getData());
}}
onError={(error, details) => {
console.error('Editor error:', error, details);
}}
onFocus={(event, editor) => {
console.log('Editor focused');
}}
onBlur={(event, editor) => {
console.log('Editor blurred');
}}
onAfterDestroy={(editor) => {
console.log('Editor destroyed');
}}
/>
);
}
// Disabled/read-only editor
function ReadOnlyEditor() {
return (
<CKEditor
editor={ClassicEditor}
data="<p>This content is read-only</p>"
disabled={true}
config={{
toolbar: []
}}
/>
);
}Adapter class that aligns context watchdog API with editor watchdog API for unified error handling.
/**
* Adapter for aligning context watchdog with editor watchdog API
*/
class EditorWatchdogAdapter<TEditor extends Editor> {
constructor(contextWatchdog: ContextWatchdog);
/** Set the editor creator function */
setCreator(creator: AdapterEditorCreatorFunction): void;
/** Create editor instance with configuration */
create(sourceElementOrData: HTMLElement | string, config: EditorConfig): Promise<unknown>;
/** Register event listener (currently supports 'error' event) */
on(event: string, callback: (data: { error: Error; causesRestart?: boolean }) => void): void;
/** Destroy the editor instance */
destroy(): Promise<unknown>;
/** Access to the current editor instance */
get editor(): TEditor;
}
type AdapterEditorCreatorFunction<TEditor = Editor> = (
elementOrData: HTMLElement | string | Record<string, string> | Record<string, HTMLElement>,
config: EditorConfig
) => Promise<TEditor>;interface ErrorDetails {
/** Phase when error occurred */
phase: 'initialization' | 'runtime';
/** Whether the error will cause editor restart */
willEditorRestart?: boolean;
}Error Handling Example:
import React from 'react';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import { ClassicEditor } from 'ckeditor5';
function EditorWithErrorHandling() {
const handleError = (error: Error, details: ErrorDetails) => {
console.error(`Editor error in ${details.phase} phase:`, error.message);
if (details.willEditorRestart) {
console.log('Editor will restart automatically');
} else {
console.log('Manual intervention may be required');
}
// Custom error reporting
reportErrorToService(error, details);
};
return (
<CKEditor
editor={ClassicEditor}
data="<p>Content with error handling</p>"
onError={handleError}
watchdogConfig={{
crashNumberLimit: 3,
onErrorCallback: (error) => {
console.log('Watchdog error callback:', error);
}
}}
/>
);
}When using CKEditor within a CKEditorContext, the component automatically integrates with the shared context for resource optimization.
import React from 'react';
import { CKEditor, CKEditorContext } from '@ckeditor/ckeditor5-react';
import { ClassicEditor, Context } from 'ckeditor5';
function EditorsWithSharedContext() {
return (
<CKEditorContext context={Context} contextWatchdog={Context.ContextWatchdog}>
<CKEditor
editor={ClassicEditor}
data="<p>First editor</p>"
contextItemMetadata={{ name: 'editor1' }}
/>
<CKEditor
editor={ClassicEditor}
data="<p>Second editor</p>"
contextItemMetadata={{ name: 'editor2' }}
/>
</CKEditorContext>
);
}