DEV Community

Honeybadger Staff for Honeybadger

Posted on • Originally published at

How to build a rich text editor for your React app with CKEditor 5

This article was originally written by Muhammed Ali on the Honeybadger Developer Blog.

Creating a dynamic, user-friendly interface for your React application can be a challenging task. One of the most important aspects of any application is the ability of users to easily create and edit content. That's where a WYSIWYG (What You See Is What You Get) editor comes in. A WYSIWYG editor provides a rich text-editing experience for users, allowing them to easily format text, add images and links, and more.

In this article, you will learn how to build a WYSIWYG editor for your React application. With this, you can go as far as creating something like Google Docs for your application. If you are trying to build a blog, you will not need to touch the code when you want to publish an article. Here, we will build a note application that stores its data on the local storage and then displays the created notes.

You can find the complete code on GitHub.

Introduction to CKEditor 5

CKEditor 5 is a JavaScript-based rich text editor that provides a user-friendly interface for creating and editing content. It is designed to be easily integrated into web applications and can be customized to suit the specific needs of a project. CKEditor 5 offers a wide range of features, such as text formatting, media embedding, undo/redo, and more. It also supports a variety of languages and can be used on both desktop and mobile devices. It's an open-source project that can be easily integrated into your web application and customized according to your needs.

Features of CKEditor 5

CKEditor 5 has a variety of features that make it a powerful and versatile text editor. Here are some of the main features:

  • Advanced text formatting: CKEditor 5 allows users to apply a wide range of text formatting options, including bold, italic, underline, and more.
  • Media embedding: Users can easily insert images, videos, and other media into their content and align, resize, and caption them.
  • Undo/Redo: Users can easily undo and redo any changes they make to their content.
  • Customizable interface: CKEditor 5 has a customizable interface that can be tailored to the specific needs of a project.
  • Collaboration: CKEditor 5 has a built-in collaboration feature, allowing multiple users to work on the same document in real time.
  • Plugins and add-ons: CKEditor 5 has a wide range of available plugins and add-ons, which can be used to extend its functionality.
  • Multilanguage support: CKEditor 5 supports a variety of languages, making it easy to use for users around the world.
  • Mobile support: CKEditor 5 is fully responsive and can be used on both desktop and mobile devices.

Developing the editor for the React app

This code is a React component called "App" that creates a simple note-taking application. The component uses the CKEditor library to provide a rich text editor for users to create and edit notes, and it stores the notes in the browser's local storage so that they persist even if the user closes the application or refreshes the page.

Start by creating a new project using create-react-app:

npx create-react-app app
cd app
Enter fullscreen mode Exit fullscreen mode

Now install the necessary dependencies for CKeditor 5:

npm install --save @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic
Enter fullscreen mode Exit fullscreen mode

Remove what you have in the App.js file. Then your component will begin by importing the necessary libraries and modules, including React, the CKEditor library, and a specific version of the CKEditor called ClassicEditor. It also imports a CSS file called App.css, which is used to style the component.

import React, { Component } from 'react';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import './App.css';
Enter fullscreen mode Exit fullscreen mode

The component's constructor method initializes the component's state with an empty array called notes to store the notes and an empty string called currentNote to store the note currently being edited.

class App extends Component {
    constructor(props) {
        this.state = {
            notes: [],
            currentNote: ""


Enter fullscreen mode Exit fullscreen mode

The component's componentDidMount() method is called when the component is first rendered, and it retrieves any notes that were previously saved in local storage and sets the component's "notes" state accordingly.

componentDidMount() {
    // Retrieve notes from local storage
    let storedNotes = localStorage.getItem("notes");
    if (storedNotes) {
        this.setState({ notes: JSON.parse(storedNotes) });

Enter fullscreen mode Exit fullscreen mode

The handleEditorChange method updates the component's currentNote state with the latest data from the CKEditor whenever the user makes changes to the note being edited.

handleEditorChange = (event, editor) => {
    this.setState({ currentNote: editor.getData() });

Enter fullscreen mode Exit fullscreen mode

The handleSaveNote method is called when the user clicks the "Save Note" button. It adds the current note to the component's notes state and saves the updated notes to local storage. Then, it clears the currentNote state so that the user can start writing a new note.

handleSaveNote = () => {
    // Add the current note to the notes array
    let newNotes = [...this.state.notes, this.state.currentNote];
    this.setState({ notes: newNotes });

    // Save the notes array to local storage
    localStorage.setItem("notes", JSON.stringify(newNotes));

    // Clear the current note
    this.setState({ currentNote: "" });

Enter fullscreen mode Exit fullscreen mode

The next step is to render the notes array in the UI. This is done in the render() method of the App component. Inside the render() method, we have a div element with the class of notes-container. Inside this div, we use the map() function to iterate through the notes array and create a new div element for each note. The key prop is set to the index of the note in the array to ensure that React can keep track of the elements.

render() {
    return (
      <div className="App">
          <h2>Note Application</h2>
              editor={ ClassicEditor }
              onChange={ this.handleEditorChange }

          <button onClick={this.handleSaveNote}>Save Note</button>
          <h3>Saved Notes:</h3>
          <div className="notes-container">
              {, index) => {
                  return <div key={index} className="note" dangerouslySetInnerHTML={{__html: note}} />
Enter fullscreen mode Exit fullscreen mode

The dangerouslySetInnerHTML prop is used to render the HTML content of the note inside the div. This is a React feature that should be used with caution, as it can introduce security vulnerabilities if not used properly.

Finally, at the bottom of the code, the App component is exported so that it can be used in other parts of the application.

export default App;
Enter fullscreen mode Exit fullscreen mode

Now, paste the following code in App.css. This is just basic styling for the note application.

.notes-container {
  margin: 20px 0;
  padding: 20px;
  border: 1px solid rgb(88, 80, 80);
  border-radius: 5px;

.note {
  margin: 10px 0;
  padding: 10px;
  border-radius: 5px;
  background-color: #a7a5a5;

.App {
  border: 5px solid gray;
  padding: 50px;
  border-radius: 5px;
Enter fullscreen mode Exit fullscreen mode

Now, you can run your application with the following command:

npm start
Enter fullscreen mode Exit fullscreen mode

complete application


This code creates a simple note-taking application that allows the user to create and save notes using the CKEditor5 rich text editor. The notes are stored in the browser's local storage so that they persist even when the user closes the browser or refreshes the page. The notes are displayed in a list in the UI and can be rendered with their original formatting.

You can learn more about CKEditor 5 by reading the official documentation and see everything it provides and its limitations.

Top comments (0)