Why is it important to know about Rich Text Editors? You might have seen Intro section like above on instagram, facebook and on other platforms as well. They support a lot of cool features like emojis, hashtags, @ mentions and others stuff as well. And Even other types of stylings as well ( like BOLD, ITALIC, BLOCKQUOTE e.t.c ). Have you ever wondered how to implement this in your own react app? If yes, then you are at the right place as after going through this article you will be able to make your own Rich Text Editors like that. Oh, 😄 as the last line and the title suggests this article is for those who are aware of basics of React, that’s the only pre-requisite I promise. So make sure, you are comfortable with React before reading this article. Let’s Start Making Our Own Rich Text Editor Before actually starting to write the React code, we need React ecosystem, which means all those Webpack configurations, and configurations for babel transpiler which is an important part but doing all those things from scratch will overshadow rich text editors for which this whole article is dedicated for. Thanks, Facebook for their open source project using which we can start making React App by writing one single command into your terminal. create-react-app So let’s make our React app using create-react-app. I will not install this package globally in my system instead I will use npx ( It will automatically install a package with that name from the npm registry for you, and invoke it. When it’s done, the installed package won’t be anywhere in your globals, so you won’t have to worry about pollution in the long-term ). npx create-react-app myappcd myappnpm start Boom, your react app is hosted on localhost:3000/. You will have a directory structure like this my-app├── README.md├── node_modules├── package.json├── .gitignore├── public│ ├── favicon.ico│ ├── index.html│ └── manifest.json└── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js So finally, we are ready to actually code our Rich Text Editor( excited ❕ ❕ ). So what are we going to make? Check My . Try typing ( : , @, or any link ) you can clearly see the power of Rich Text Editors. You might have also seen some variables like ( And as soon as you click them you get mustache syntax of handlebars. Don’t be afraid, if you are not aware of handlebars. It is not required for this article. I implemented them, for one of my projects where I needed to make an interface where each organization can design their own email templates for some action triggers. Rich-Text-Editor organization.name, organization.email and many others). Basics of draft-js The basic component used in Draft-js is an Edit control. If we compare a text input to an Edit control, a Text input has a value that is a text string. In an Edit control, we need more than simple text, we need an object that holds the text, cursor position etc. Instead of just text, we use an EditorState object. There are a few key things that one must know to use the Editor control successfully: The EditorState control is immutable. This means you never change it or any of its properties. Instead, if you want to change something like the text, you use a method ( onChange() to be specific ) that gives you back an entirely new EditorState which is a copy of the old EditorState and your new changes ( Remember “state” object in React, just like we used setState() method to change the state instead of directly mutating the object ) The new EditorState is then given to the edit control where you can see your changes. The EditorState controls have child objects that show the actual state of what is being represented in the editor including text, cursor/selection, styling etc. Definitions The object responsible for the current state as represented in the Editor EditorState: The object responsible for the text in the Editor. Content is made up of blocks of Content. ContentState: The object responsible for the cursor and the cursor’s selection area SelectionState: Metadata that can be added to a portion of text Entities: These were some of the basic terminologies which you gonna see everywhere in code and draft-js as well. docs Our Project Let’s come back to our react-app. You can clone this project from for side by side reviewing, but I will recommend you to make it on your own. App.js in the project is our root component. Which looks like this Github React, { Component } 'react'; MyEditor './Editor' import from import from App Component {render() { (<MyEditor/>);}} class extends return App; export default Now, where is that MyEditor coming from? It is coming from Editor.js our other component. Now, before making this component let’s install draft-js and draft-js-plugins-editor. Wait, you can implement your editor without the later npm library also. So why we are importing it? The answer is, it gives you a way to add a lot of plug-n-play extensions in your editor out of the box like (mention, emojis, linkify, inline-toolbar e.t.c ). This editor has been built over Editor of draft-js only. Since this library gives the editor only. For other kinds of stuff, we still require draft-js. For more details check out . this npm install draft-js draft-js-plugins-editor --save Okay, Now we are ready for Editor.js React, { Component } 'react'; { convertToRaw, EditorState, RichUtils } 'draft-js'; Editor 'draft-js-plugins-editor'; import from import from import from Import these things. MyEditor Component { class extends constructor(props) { _super_(props); _this_.state = { editorState: EditorState.createEmpty() }; _this_.onChange = (editorState) => _this_.setState({editorState}); } handleKeyCommand = ( command, editorState ) => { newState;newState = RichUtils.handleKeyCommand( editorState, command ); ( newState ) { .onChange(newState); "handled"} let if this return 'non-handled' return }; <Editor ={ .state.editorState } ={ .onChange } ={ .handleKeyCommand }/> editorState this onChange this handleKeyCommand this } We have initiated the empty state of the editor using the EditorState.createEmpty() method and added it into the state of MyEditor Component. So that, the component re-renders when the Editor State changes. Editor component has 3 props first one is editorState, and the next one is onChange, which shows that it is a component, and the third one is handleKeyCommand which uses RichUtils which provides rich text editing for the selected state. Try typing cmd + b, cmd +i, cmd + u and cmd + z in your editor and see the magic. You can also make custom commands check . That is what Rich utils do for us. Now, let us add some draft-js plugins and see the magic. controlled here Mention Plugin import the plugin and its CSS file. createMentionPlugin, { defaultSuggestionsFilter } 'draft-js-mention-plugin'; 'draft-js-mention-plugin/lib/plugin.css'; import from import create a mention.js file and feed some data into it and then export data from that file. mention.js mentions = [{name: 'Matthew Russell',link: 'https://twitter.com/mrussell247',avatar: 'https://pbs.twimg.com/profile_images/517863945/mattsailing_400x400.jpg',},{name: 'Julian Krispel-Samsel',link: 'https://twitter.com/juliandoesstuff',avatar: 'https://avatars2.githubusercontent.com/u/1188186?v=3&s=400',},{name: 'Jyoti Puri',link: 'https://twitter.com/jyopur',avatar: 'https://avatars0.githubusercontent.com/u/2182307?v=3&s=400',},{name: 'Max Stoiber',link: 'https://twitter.com/mxstbr',avatar: 'https://pbs.twimg.com/profile_images/763033229993574400/6frGyDyA_400x400.jpg',},{name: 'Nik Graf',link: 'https://twitter.com/nikgraf',avatar: 'https://avatars0.githubusercontent.com/u/223045?v=3&s=400',},{name: 'Pascal Brandt',link: 'https://twitter.com/psbrandt',avatar: 'https://pbs.twimg.com/profile_images/688487813025640448/E6O6I011_400x400.png',},]; const mentions; export default cool, now import this file in your MyEditor Component. mentions './mentions'; import from Now initialize this plugin mentionPlugin = createMentionPlugin(); { MentionSuggestions } = mentionPlugin; // mention plugin ( do it globally out of MyEditor class )const const Now add this component as a sibling to MyEditor and wrap both these components into a div tag or react fragment. <div><MyEditor ... /><MentionSuggestions = { .onSearchChange } = { .state.suggestions } = { .onAddMention }/></div> onSearchChange this suggestions this onAddMention this in constructor modify this line, .state = {editorState: EditorState.createEmpty(), suggestions: mentions}; this implement these two methods onSearchChange = ({ value }) => { .setState({suggestions: defaultSuggestionsFilter(value, mentions),});}; this onAddMention = () => { // add logic after mentioning someone here }; Cool, you are ready with @ mentions in your editor. Try typing @. This plugin required some extra work, other plugins available are very direct and easy to use. Simply import them, initialize them, and in the end, add as a sibling component to your MyEditor. That’s it, you are ready to use them. Check out the code in the example provided in my GitHub repo. Now let’s see how I added Variable and BlockVariable Component which are atomic in nature i.e on backspace whole block gets deleted. So that the variable in the template didn’t get polluted. Check the Variable.js and BlockVariable.js files in the The code is very simple if you go through it once, it will be clear. repo. The main concept used in them is Modifiers AtomicBlockUtils Entity I hope this article will help you to get started with the draft-js. Draft-js has a lot of things, which you should try to find out. More you dive into it, more you can play with your editor. I will try to write a few more articles on draft-js advanced topics. Some resources for getting started with it: Draft-js docs One of the I found out. good resource Give a clap if you liked it and yes if you have any queries you can ask them down here I will try to help you out. Happy Coding 😃.