CKEditor 4 WYSIWYG Editor React Integration Documentation
The React integration allows you to implement CKEditor 4 as a React component, using the <CKEditor />
JSX tag or useCKEditor
hook.
The following examples showcase the most important features of the CKEditor 4 WYSIWYG editor React integration.
Click the tab below to change an example.
Get Sample Source Code
- Classic editor
import React from 'react'; import ReactDOM from 'react-dom'; import { CKEditor } from 'ckeditor4-react'; ReactDOM.render( <CKEditor initData={<p>This is a CKEditor 4 WYSIWYG editor instance created by ️⚛️ React.</p>} />, document.getElementById( 'app' ) );
- Inline editor
import React from 'react'; import ReactDOM from 'react-dom'; import { CKEditor } from 'ckeditor4-react'; ReactDOM.render( <CKEditor type="inline" initData={<p>This is a CKEditor 4 WYSIWYG editor instance created by ️⚛️ React.</p>} />, document.getElementById( 'app' ) );
- Editor with custom event handlers and configuration
import React from 'react'; import ReactDOM from 'react-dom'; import { CKEditor } from 'ckeditor4-react'; const { useState } = React; const ConfigEvents = () => { const [ events, setEvents ] = useState( [] ); const logEvent = ( evt ) => { evt.timestamp = new Intl.DateTimeFormat( 'en', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' } ).format( new Date() ); setEvents( events => [ evt, ...events ] ); } const clearEvents = () => { setEvents( [] ); } return ( <div> <h2>WYSIWYG editor with custom event handlers and configuration</h2> <p> Editors created with the CKEditior 4 React component are highly customizable. It is possible to overwrite every configuration setting using the <code>config</code> property and passing an object containing the configuration to it. </p> <p> Additionally, the CKEditor 4 WYSIWYG editor component for React allows you to bind any event handler using properties with names starting with <code>on</code>, followed by the name of the event with the first letter capitalized. The following example shows how to bind several common CKEditor 4 events and apply custom toolbar configuration. </p> <CKEditor initData="This is a CKEditor 4 WYSIWYG editor instance created by ️⚛️ React." config={{ toolbar: [ [ 'Source' ], [ 'Styles', 'Format', 'Font', 'FontSize' ], [ 'Bold', 'Italic' ], [ 'Undo', 'Redo' ], [ 'EasyImageUpload' ], [ 'About' ] ], extraPlugins: 'easyimage', removePlugins: 'image', cloudServices_uploadUrl: 'https://33333.cke-cs.com/easyimage/upload/', cloudServices_tokenUrl: 'https://33333.cke-cs.com/token/dev/ijrDsqFix838Gh3wGO3F77FSW94BwcLXprJ4APSp3XQ26xsUHTi0jcb1hoBt' }} onFocus={logEvent} onBlur={logEvent} onChange={logEvent} onSelectionChange={logEvent} /> <h3>Events Log</h3> <small>To check additional details about every event, consult the console in the browser developer tools.</small> <EventLog stream={events} /> <button onClick={clearEvents}>Clear events log</button> </div> ); } const EventLog = ( { stream } ) => { return ( <div className="event-log"> <ul className="event-log__events"> { stream.map( event => { return ( <li className="event-log__event"> <Event data={event} /> </li> ) } ) } </ul> </div> ); } const Event = ( { data: { name, timestamp } } ) => { return ( <> {timestamp} – {name} </> ); } ReactDOM.render( <ConfigEvents />, document.getElementById( 'app' ) );
- Lifting state up
import React from 'react'; import ReactDOM from 'react-dom'; import { useCKEditor, CKEditorEventAction } from 'ckeditor4-react'; const { useEffect, useState, useReducer, useMemo } = React; const Editor = ( { dispatch, state } ) => { const [ element, setElement ] = useState(); const { editor } = useCKEditor( { element, dispatchEvent: dispatch, subscribeTo: [ 'focus', 'change' ], initContent: state.data } ); /** * Invoking `editor.setData` too often might freeze the browser. */ const setEditorData = useMemo( () => { if ( editor ) { return new CKEDITOR.tools.buffers.throttle( 500, data => { if ( editor ) { editor.setData( data ); } } ).input; } }, [ editor ] ); /** * Sets editor data if it comes from a different source. */ useEffect( () => { if ( state.currentEditor !== 'CKEditor' && setEditorData ) { setEditorData( state.data ); } }, [ setEditorData, state ] ); return <div ref={setElement} />; } const TextAreaEditor = ( { dispatch, state } ) => { const handleTextAreaChange = evt => { const value = evt.currentTarget.value; dispatch( { type: 'textareaData', payload: value } ); }; const handleFocus = () => { dispatch( { type: 'textareaFocus' } ); }; return ( <> <p> <label htmlFor="editor-editor">The editor content:</label> </p> <p> <textarea id="editor-editor" className="binding-editor" value={state.data} onChange={handleTextAreaChange} onFocus={handleFocus} /> </p> </> ); } const reducer = ( state, action ) => { switch ( action.type ) { case 'textareaData': { return { ...state, data: action.payload }; } case 'textareaFocus': { return { ...state, currentEditor: 'textarea' }; } case CKEditorEventAction.change: { return { ...state, data: state.currentEditor === 'CKEditor' ? action.payload.editor.getData() : state.data }; } case CKEditorEventAction.focus: { return { ...state, currentEditor: 'CKEditor' }; } } } const StateLifting = () => { const [ state, dispatch ] = useReducer( reducer, { data: '<p>This is a CKEditor 4 WYSIWYG editor instance created by ️⚛️ React.</p>', currentEditor: undefined } ); return ( <div> <h2>Lifting state up</h2> <p> Shared state of React components can be moved <a href="https://reactjs.org/docs/lifting-state-up.html">higher up the React tree</a>. In the example below, CKEditor 4 WYSIWYG editor component shares content with other components. </p> <p> Additionally, <code>useCKEditor</code> hook is used to access <code>editor</code> instance directly and use its methods imperatively, e.g. <code>editor.setData( data )</code>. </p> <TextAreaEditor dispatch={dispatch} state={state} /> <div className="editor-instance"> <Editor dispatch={dispatch} state={state} /> </div> <div className="editor-preview"> <h2>Rendered content</h2> <div dangerouslySetInnerHTML={{ __html: state.data }}></div> </div> </div> ); } ReactDOM.render( <StateLifting />, document.getElementById( 'app' ) );