The WYSIWYG text editor is a user interface that allows you to edit text and preview the result immediately. Building the rich text editor from scratch is a complicated and time-consuming task, hence external NPM packages such as “draft-js” and “react-draft-wysiwyg” will simplify the development process.
The React app will have the following features:
- Option to select the font size of the text between 8px to 30px.
- Include inline stylings such as bold, italics, underline and strikethrough.
- Feature to add emoji characters in the text.
- Allow users to embed images along with text characters.
- Display HTML code output of text editor content.
1) Install “draft-js”, “react-draft-wysiwyg“ and “draftjs-to-html” npm packages
- “react-draft-wysiwyg” package: Provides components to build customizable Wysiwyg editor with React JS and Draft JS.
- “Draft JS” package: It is a rich text editor framework for React JS and provides functionalities for the react-draft-wysiwyg package.
- “draftjs-to-html” package: Includes functionalities to parse raw “Draft JS” editor data into HTML code.
npm i draft-js react-draft-wysiwyg draftjs-to-html
// For projects configured with yarn
yarn add draft-js react-draft-wysiwyg draftjs-to-html
2) React States to control editor content
The content of the text editor is dynamically updated by the user, hence React state is required to control the text editor content.
const [editorState, setEditorState] = useState(EditorState.createEmpty());
Additionally, handleChange function updates the state with “data” parameter on every function call.
const handleChange = (data) => {
setEditorState(data);
};
3) Customize toolbar options
The default toolbar of the text editor from “react-daft-wysiwyg” package will display all the available options. We can customize the toolbar options based on the requirement through <Editor/> component props.
The tollbarOptions object is the customized value for toolbar property to display inline, font size, image, and emoji toolbar options.
const toolbarOptions = {
options: ["inline", "fontSize", "image", "emoji"],
inline: {
options: ["bold", "italic", "underline", "strikethrough"],
},
};
4) Include editor component into JSX code
The <Editor/> component imported from “react-draft-wysiwyg” package will render the WYSIWYG editor on screen, customized based on values passed through the props.
The CSS file imported from the library will include CSS styles for the editor.
import { Editor } from "react-draft-wysiwyg";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
<Editor
editorState={editorState}
onEditorStateChange={handleChange}
wrapperClassName="editor-wrapper"
editorClassName="message-editor"
toolbarClassName="message-toolbar"
toolbar={toolbarOptions}
/>
5) Display HTML code output on the screen
The final step involves displaying output HTML code based on the editor content entered by the user. The “draftjs-to-html” package provides functionality to convert the editor content into HTML code.
import draftToHtml from "draftjs-to-html";
var htmlData = useMemo(
() => draftToHtml(convertToRaw(editorState.getCurrentContent())),
[editorState]
);
<div className="html-output">{htmlData}</div>
Final Solution Code
App.js
import React, { useState, useMemo } from "react";
import { EditorState, convertToRaw } from "draft-js";
import { Editor } from "react-draft-wysiwyg";
import draftToHtml from "draftjs-to-html";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import "./styles.css";
export default function App() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const handleChange = (data) => {
setEditorState(data);
};
var htmlData = useMemo(
() => draftToHtml(convertToRaw(editorState.getCurrentContent())),
[editorState]
);
const toolbarOptions = {
options: ["inline", "fontSize", "image", "emoji"],
inline: {
options: ["bold", "italic", "underline", "strikethrough"],
},
};
return (
<div className="app">
<Editor
editorState={editorState}
onEditorStateChange={handleChange}
wrapperClassName="editor-wrapper"
editorClassName="message-editor"
toolbarClassName="message-toolbar"
toolbar={toolbarOptions}
/>
<div className="html-output">{htmlData}</div>
</div>
);
}
styles.css
.app {
display: flex;
flex-direction: column;
padding: 10% 25%;
margin-top: 20px;
gap: 30px;
}
.editor-wrapper {
border: 1px solid #c4cdd5;
}
.message-toolbar {
border-bottom: 1px solid #c4cdd5;
margin-bottom: 0px;
padding: 6px 5px;
}
.message-editor {
height: 150px;
font-size: 16px;
padding: 0px 10px;
}
.rdw-option-wrapper {
min-width: 35px;
height: 30px;
}
.html-output {
border: 1px solid silver;
padding: 20px;
background-color: #fafafa;
}