Build your draft-js editor fast and easily with contenido!
Tags: react, draftjs, contenidojs, wysiwyg
Published: 2023-04-14 14:54:30

## What is this post about?
From creating a simple comment input box with some basic features to creating a rich text editor for your CMS, finding the proper solution and development path can be challenging and time consumable. In this post, I'll introduce you to a way to create a rich text editor (RTE) with [draft-js](https://draftjs.org/) and [contenidojs](https://github.com/HPouyanmehr/contenido) that will adapt to your UI library and your design principles.

## What we're going to check? (Table of contents)
* [`draft-js` introduction](#draft-js-introduction)
* [`contenidojs`](#contenidojs)
* [`contenidojs` + TypeScript](contenidojs-and-typescript)
* [`contenidojs` compatibility with different UI libs](contenidojs-and-ui-libraries-and-styling)
* [How to build a simple RTE in `react` with `contenidojs`?](#how-to-build-a-simple-rte-in-react-with-contendiojs)
* [`contenidojs` + `nextjs`](contenidojs-and-nextjs)

## <a name='draft-js-introduction'></a>Draft-JS (Powerful but confusing)

As the [draft-js official website](https://draftjs.org/) says, draft-js is a: 
> Rich Text Editor Framework for React

Although the draft-js home page example is basic, the true power that comes with it is a lot. You can almost create whatever you like to be your RTE. Draft-js lets you to do simple inline styling, media handling and add complicated stuffs like mentions and hashtags.

You'll indeed have a first-class rich text editor, but it takes a lot of effort and time for more complicated things. You'll be ok if you just need to add `bold` and `italic` styles for example. But things became harder to handle and understand when your needs of the editor is more than that. Unfortunately, the draft-js documentation isn't that comprehensive and sometimes you can't find your answers on the docs. This is the point that `contenido-js` become handy.
 

## <a name='contenidojs'></a>ContenidoJS (A game changer for draft-js)
[Contenidojs](https://www.contenidojs.com/) is a react library on top of draft-js. This means it will use draft-js as its core and add something that makes it more powerful and easier to use. If you have experience in using the redux and redux toolkit, You can feel the difference here as well. You can think of draft-js as redux and the contenidojs will be RTK (Redux Toolkit). 

We'll check out the contenidojs library compatibility with Next.js and UI libraries later on in this article, but these are some of contenido's features and benefits:

* Basic inline styles as well as custom ones
* Ready-to-use utilities for headings, lists, blockquotes, and more.
* Ready-to-use utilities for handling media. (You'll get mad if you want to implement these just with `draft-js`)
* Text alignment utilities
* Style, block type, and media clearance
* Shortcut support and customization
* Utilities to limit the user, count the editor entities

Check out the contenido's features [here](https://www.contenidojs.com/docs/getting-started/overview#features).


## <a name='contenidojs-and-typescript'></a>ContenidoJS and TypeScript
While `draft-js` is written in JS and you need to add types to it manually, [`contenidojs`](https://www.npmjs.com/package/contenido) is written in TypeScript and you don't need to do extra stuffs for type handling.

## <a name='contenidojs-and-ui-libraries-and-styling'></a>ContenidoJS + UI Libraries and Styling
You may find a lot of packages and frameworks that offer you a solution to create and add an RTE to your project easily but there is a common issue and **its styling**. You may find customization in their docs but when you try to customize the editor you won't be able to customize them that much. Despite other libraries, contenidojs isn't an 'install and use' text editor. It will do all the editor-handling stuff and lets you focus on the UI. So you can easily build an RTE with your favorite UI library like Material-UI (MUI), Tailwind CSS, Bootstrap, Ant Design, Chakra UI, and ...

> The main purpose is to give you the ability to create your custom look rich-text editor a lot faster and easier.
> [Contenido's Home Page](https://www.contenidojs.com/)

## <a name='how-to-build-a-simple-rte-in-react-with-contendiojs'></a>How to build a simple RTE in `react` with `contenidojs`?
This is an example of using `contenidojs` in your code. For more examples check out the official [docs](https://www.contenidojs.com/docs/getting-started/overview).

### Setup

- First we'll create a react app.
TypeScript:

```bash
npx create-react-app contenidojs-tutorial --template typescript
```

JavaScript:

```bash
npx create-react-app contenidojs-tutorial
```

- Then install `draft-js`.

TypeScript:

```bash
npm i draft-js @types/draft-js
```
JavaScript:

```bash
npm i draft-js
```

- And finally install contenidojs:
```bash
npm i contenido
```

ContenidoJS is written in TypeScript and there is no need to install types for that.

### Usage
This is an example of an editor component with shortcuts and `bold`, `italic` and `underline` utilities. 

```ts
import { useState } from 'react';
import { EditorState } from 'draft-js';
import { 
  Editor, 
  isBold, 
  toggleBold ,
  isItalic,
  toggleItalic,
  isUnderline,
  toggleUnderline,
  getDefaultKeyBindingFn,
  shortcutHandler
} from 'contenido';

const CustomEditor = () => {
  const [editorState, setEditorState] = 
    useState(EditorState.createEmpty());

  const toolbarButtons = [
    {name: 'Bold', handler: toggleBold, detector: isBold},
    {name: 'Italic', handler: toggleItalic, detector: isItalic},
    {name: 'Underline', handler: toggleUnderline, detector: isUnderline},
  ]

  return (
    <>
      <Editor 
        editorState={editorState} 
        onChange={setEditorState}
        handleKeyCommand={shortcutHandler(setEditorState)}
        keyBindingFn={getDefaultKeyBindingFn}
      />
      {
        toolbarButtons.map(btn => (
          <button
            key={btn.name}
            onMouseDown={(e) => {
              e.preventDefault();
              btn.handler(editorState, setEditorState)
            }}
            style={{
              color: btn.detector(editorState) ? 
                'skyblue' 
                : 
                'black'
            }}
          >
            {btn.name}
          </button>
        ))
      }
    </>
  )
}

export default CustomEditor;
```

For more examples check out the official [site](https://www.contenidojs.com).

## <a name='contenidojs-and-nextjs'></a>ContenidoJS and Next.js
You can use contenidojs with SSR as well. The only thing that you need to pay attention is the very first state of your editor. Each block in draft-js state have a unique key. This may cause issues when you're using SSR frameworks for react like Next.js. To solve the issue (Base on this [doc](https://www.contenidojs.com/docs/helpers/empty-raw-content-state#example)):

```ts
import { useState } from 'react';
import { EditorState } from 'draft-js';
import { Editor, emptyRawContentState } from 'contenido';

const emptyContentState = convertFromRaw(emptyRawContentState)

const Demo = () => {
  const [editorState, setEditorState] = useState(
    EditorState.createWithContent(emptyContentState)
  );

  return (
      <Editor
        editorState={editorState}
        onChange={setEditorState}
        editorRef={editorRef}
      >
  )
}

export default Demo;
```


---

[![A banner of become a backer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnb2hbuk8abtl1amqxhi.jpg)](https://hpouyanmehr.com/backers#donate)

Hi! I'm **Hosein Pouyanmehr**. I enjoy sharing what I learn and what I find interesting. Let's connect on [LinkedIn](https://www.linkedin.com/in/hpouyanmehr/).

See my code interests on [GitHub](https://github.com/HPouyanmehr).