Rich Text Editor using Draft.JS

Visakh Vijayan
2 min readMay 8, 2024

--

Let us face it. The normal text area is not good enough these days. We need all the formatting possible these days so that the customers can present data in an impressive format.

That is where draft.js comes in. A cool text editor for React Apps. Here is how we made our text area exciting for our customers.

import { EditorState, ContentState, convertFromHTML } from 'draft-js';
import { stateToHTML } from 'draft-js-export-html';
import React, { useEffect, useState } from 'react';
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';

type RichTextAreaProps = {
name: string;
onChange: (value: any) => void;
onReset?: () => void;
placeholder?: string;
reset?: boolean;
value: string;
};

const RichTextArea: React.FC<RichTextAreaProps> = ({
name,
onChange,
value,
placeholder = 'Enter Details',
reset,
onReset,
}) => {
const [editorState, setEditorState] = useState(EditorState.createEmpty());

const handleEditorChange = (newEditorState) => {
setEditorState(newEditorState);

const rawContentState = editorState.getCurrentContent();
const html = stateToHTML(rawContentState);

onChange({
target: {
name,
value: html,
},
});
};

useEffect(() => {
const blocksFromHTML = convertFromHTML(value);
const contentState = ContentState.createFromBlockArray(blocksFromHTML);
setEditorState(EditorState.createWithContent(contentState));
}, []);

useEffect(() => {
if (reset) {
setEditorState(EditorState.createEmpty());

const blocksFromHTML = convertFromHTML(value);
const contentState = ContentState.createFromBlockArray(blocksFromHTML);

setEditorState(EditorState.createWithContent(contentState));
onReset();
}
}, [reset]);

return (
<div className="w-full bg-white p-2">
<Editor
name={name}
placeholder={placeholder}
editorState={editorState}
onEditorStateChange={handleEditorChange}
toolbar={{
options: ['inline', 'fontSize', 'list', 'textAlign', 'link', 'image'],
inline: {
options: ['bold', 'italic', 'underline'],
},
list: {
options: ['unordered', 'ordered'],
},
textAlign: {
options: ['left', 'center', 'right'],
},
link: {
defaultTargetOption: '_blank',
},
image: {
defaultSize: {
height: 'auto',
width: '100%',
},
},
}}
/>
</div>
);
};

export default RichTextArea;
  1. Editor is the component provided by draft.js out of the box. Just by adding that you get a rich text editor with a default toolbar.
  2. The toolbar prop allows you to customize all the formatting options you want to show in the toolbar
  3. editorState is what controls the state or whatever the user is typing into the editor
  4. The Editor is actually connected to formik and hence the name and onChange calls.
  5. By default the editor returns an EditorState object which has to be converted to HTML to make sense while sending it to backend via stateToHTML(rawContentState) call.
  6. The reverse is also done when loading the editor with data from backend via ContentState.createFromBlockArray.
<FormControl
label="Feedback"
error={formik.touched.response && formik.errors.response}
>
<RichTextArea
name="feedback"
value={formik.values.feedback}
onChange={formik.handleChange}
/>
</FormControl>

This is how the <RichTextArea> component is used. The <FormControl> actually wraps the formik provider into this.

And that is how it looks.

Happy coding!

--

--

Visakh Vijayan
Visakh Vijayan

Written by Visakh Vijayan

Techie from Kerala, India. Days are for coding, nights for weaving tales of tech, travel, and finance. Join me in exploring this multifaceted journey

No responses yet