DEV Community

Cover image for Build your draft-js editor fast and easily with contenido!
Hosein Pouyanmehr
Hosein Pouyanmehr

Posted on • Edited on

Build your draft-js editor fast and easily with contenido!

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 and contenidojs that will adapt to your UI library and your design principles.

What we're going to check? (Table of contents)

Draft-JS (Powerful but confusing)

As the draft-js official website 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.

ContenidoJS (A game changer for draft-js)

Contenidojs 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.

ContenidoJS and TypeScript

While draft-js is written in JS and you need to add types to it manually, contenidojs is written in TypeScript and you don't need to do extra stuffs for type handling.

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

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.

Setup

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


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


Enter fullscreen mode Exit fullscreen mode

JavaScript:



npx create-react-app contenidojs-tutorial


Enter fullscreen mode Exit fullscreen mode
  • Then install draft-js.

TypeScript:



npm i draft-js @types/draft-js


Enter fullscreen mode Exit fullscreen mode

JavaScript:



npm i draft-js


Enter fullscreen mode Exit fullscreen mode
  • 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;


Enter fullscreen mode Exit fullscreen mode

For more examples check out the official site.

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):



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;


Enter fullscreen mode Exit fullscreen mode

A banner of become a backer

Hi! I'm Hosein Pouyanmehr. I enjoy sharing what I learn and what I find interesting. Let's connect on LinkedIn.

See my code interests on GitHub.

Top comments (4)

Collapse
 
ndotie profile image
ndotie

am copy & paste this codes to my project. and if they work 'ill be the happiest person on office planet

Collapse
 
hpouyanmehr profile image
Hosein Pouyanmehr

๐Ÿ˜๐Ÿ˜

Did it work as you expected?

Collapse
 
ndotie profile image
ndotie

Yes man. thanks.

my manager thinks am the genius they've been looking for, if only they knew..... Hahahahahaaa!!

Thread Thread
 
hpouyanmehr profile image
Hosein Pouyanmehr

You're welcome,
Happy to hear that!