14-day Cloud trial
Start today. For free.

One editor. 50+ features. Zero constraints. After your trial, retain the advanced features.

Try Professional Plan for FREE
PricingContact Us
Log InGet Started Free

How to enrich a React textarea with TinyMCE

March 22nd, 2023

6 min read

The text area and a react app expressed in symbols on a green background

Written by

Joe Robinson

Category

How-to Use TinyMCE

In a world filled with more and more distractions, an interface that customers can understand and use without confusion is more valuable than ever. An efficient UI comes from an intense push. It takes time to realize the kind of interface that goes from an average experience to a great one for customers. But that’s rarely the reality.

But how there is a framework that can help speed up building an interface. React – it’s designed for UI development at speed.

And if you want to compound your speed, and save time for developing a great UI overall, it’s worth finding the right components that work out of the box and are ready to be integrated into your app. One such component is the reliable React WYSIWYG editor like TinyMCE.

TinyMCE has a dedicated integration for React, and integrating it into your design gives a reusable React textarea to add powerful text editing capabilities for your customers anywhere it’s needed in the design requirements.

This article explains: how to get a React textarea going, and then how to enhance that textarea with TinyMCE.

How to create a simple React textarea

The following demo makes use of a CMS interface with a simple React textarea. Follow the steps outlined to get started, and try out React, or check the next section to see how TinyMCE enhances the React textarea experience.

  1. Create a new React app in your development environment:

npx create-react-app cms-demo

You should see the following result:

Creating a new React app in environment/pathway/cms-demo
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...

  1. Change into the new project directory:

cd cms-demo
  1. Change into the src/ directory, and locate the App.js file: replace the contents with the following - it’s the a demo Content Management System with a basic React textarea:

import React, { useState } from "react";
import "./styles.css";

function App() {
  const [articles, setArticles] = useState([]);
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");

  const addArticle = () => {
    const newArticle = { title: title, content: content };
    setArticles([...articles, newArticle]);
    setTitle("");
    setContent("");
  };

  return (
    <div>
           <h1>Content Management System</h1>
           
      <div>
               <label htmlFor="title">Title:</label>
               
        <input
          type="text"
          id="title"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
             
      </div>
           
      <div>
               <label htmlFor="content">Content:</label>
               
        <textarea
          id="content"
          value={content}
          onChange={(e) => setContent(e.target.value)}
        ></textarea>
             
      </div>
            <button onClick={addArticle}>Add Article</button>
           <h2>Articles:</h2>
           
      <ul>
               
        {articles.map((article, index) => (
          <li key={index}>
                       <h3>{article.title}</h3>
                       <p>{article.content}</p>
                     
          </li>
        ))}
             
      </ul>
         
    </div>
  );
}

export default App;
  1. To style the demo, create a CSS file called styles.css in the src/ directory, and add the following:

body {
    background-color: #F9FAFB;
    font-family: Arial, sans-serif;
  }
 
  h1, h2, h3 {
    color: #4D66CB;
    margin: 10px;
  }

  div {
    margin: 12px;
  }

  label {
    color: #4D66CB;
    font-weight: bold;
  }

  input, textarea {
    border: 1px solid #4D66CB;
    border-radius: 4px;
    padding: 8px;
    margin-bottom: 16px;
    font-size: 16px;
  }

  button {
    background-color: #4D66CB;
    color: #F9FAFB;
    border: none;
    border-radius: 4px;
    padding: 8px 16px;
    font-size: 16px;
    cursor: pointer;
  }

  button:hover {
    background-color: #99AEFF;
  }

  ul {
    list-style: none;
    padding: 0;
  }

  li {
    border: 1px solid #99AEFF;
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 16px;
  }

  li h3 {
    margin-top: 0;
  }

  li p {
    margin-bottom: 0;
  }
  1. To test out the app, use the npm run command, which automatically opens the demo running a React Textarea:

npm run start

 

The essential React Textarea running

 

How to set up enriched React textarea

Enhance the React textarea by installing TinyMCE with npm, and configuring it. React adds speed to your development process by letting you use reusable components. However, the TinyMCE React integration doesn’t even need a component!. That’s the main advantage of using a dedicated framework integration – it saves on integration time.

Here’s how to enhance your React textarea:

  1. Stop the demo running with Ctrl + c,  and then Install TinyMCE through npm:

npm install --save tinymce @tinymce/tinymce-react fs-extra
  1. Change out of the src/ directory and back into the top level app directory: create a file called postinstall.js. Add the following JavaScript:

touch postinstall.js
…

The JavaScript:

const fse = require("fs-extra");
const path = require("path");
const topDir = __dirname;
fse.emptyDirSync(path.join(topDir, "public", "tinymce"));
fse.copySync(
  path.join(topDir, "node_modules", "tinymce"),
  path.join(topDir, "public", "tinymce"),
  { overwrite: true }
);
  1. Open the package.json file, and update the contents to reference the new postinstall.js file:

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "postinstall": "node ./postinstall.js"
  },
  1. Modify the .gitignore file, adding the following line:

#tinymce

/public/tinymce/
  1. Copy TinyMCE to the public/ directory by running the postinstall script:

npm run postinstall
  1.  Change back into the src/ directory, and open the App.js file – import TinyMCE:

import React, { useState } from "react";
import { Editor } from "@tinymce/tinymce-react"; //1. Import TinyMCE Editor
import "./styles.css";
  1. Replace the textarea tag with TinyMCE:

<div>
         <label htmlFor="content">Content:</label>
         
  <Editor
    tinymceScriptSrc={process.env.PUBLIC_URL + "/tinymce/tinymce.min.js"}
    apiKey="your-api-key"
    init={{
      height: 300,
      plugins: [
        "a11ychecker advcode advlist advtable anchor autocorrect autosave editimage image link linkchecker lists media mediaembed pageembed powerpaste searchreplace table template tinymcespellchecker typography visualblocks wordcount",
      ],
      toolbar:
        "undo redo | blocks fontfamily fontsize | bold italic underline forecolor backcolor | alignleft aligncenter alignright alignjustify lineheight | removeformat | link ",
      menubar: false,
      block_formats: "Paragraph=p; Header 1=h1; Header 2=h2; Header 3=h3",
      content_style: `
            body {
              font-family: Arial, sans-serif;
              margin: 12px;
            }
            h1, h2, h3, p {
              color: #4D66CB;
              margin: 10px;
            }
            `,
    }}
  />
        
</div>;

At this stage, you can add in your TinyMCE API key to access our Premium plugins, as well as icons and skin packs. Replace “no-api-key” with your API key.

Note: Adding your API key to the Editor configuration also prevents the appearance of error messages about unrecognized domain names. And, the API key comes with a 14-day FREE trial of the TinyMCE Premium plugins.

  1. Restore the id=”content” identifying to the Editor:

<Editor 
          tinymceScriptSrc={process.env.PUBLIC_URL + '/tinymce/tinymce.min.js'}
          apiKey='your-API-key'
          id='content' //Add the content id back in
          init= {{
  1. Save the changes, and then restart the React demo if needed:

npm start

TinyMCE enriching the React textarea

While the demo React Content Management System (CMS) is now configured with TinyMCE, the “add article” button doesn’t seem to save the TinyMCE text area content. There are two options now:

  1. Disable the React textarea
  2. Fix the problem and get the text area value

How to disable React textarea

Disabling the textarea involves changing the <Editor> tag back to a <textarea> tag. This also involves removing the TinymceScriptSrc, ApiKey, and Init configuration from the tag.Make sure that the id remains set as “content”, and add the following event handler back into the configuration:

onChange={(e) => setTitle(e.target.value)}

It’s this event handler that was responsible for getting the textarea value, and adding it to the CMS. The demo uses a mapping function to export the textarea content: 

      <ul>
        {articles.map((article, index) => (
          <li key={index}>
            <h3>{article.title}</h3>
            <p>{article.content}</p>
          </li>
        ))}
      </ul>

Read on to see how to handle content created in the enriched React textarea.

How to get the text area value in React

Getting the textarea value from TinyMCE and adding it to Articles list is possible with the use of the getContent and setContent TinyMCE APIs. Modify the React demo event handlers with the following:

  1. Inside the addArticle function, set up a new constant called “StringtoHTML”:

const addArticle = () => {
const stringToHTML = 
  1. Set the constant to get the content of the TinyMCE window, specifically targeting the Editor with through the “content” id, and then get the content in HTML format

const stringToHTML = window.tinymce
  .get("content")
  .getContent({ format: "html" }); //Set up a constant that gets the TinyMCE text area content for use in the CMS demo
  1. Change the newArticle constant so that it sets the inner HTML of the newly saved article element as HTML and not a text string. This example makes use of the React dangerouslySetInnerHTML method.

    Note: The React dangerouslySetInnerHTML method gets the demo content working here, but is not recommended in production due to security concerns, such as Cross-Site Script attacks. Check on the React docs for more information.

const newArticle = {
  title: title,
  content: <div dangerouslySetInnerHTML={{ __html: stringToHTML }} />,
}; // 3.modify the newArticle constant so that it receives the TinyMCE editor contents in HTML format
  1. Remove “content” from the function App() list of constants as it is no longer needed.

function App() {
…
  const [setContent] = useState('');
  1. Modify the newArticle setContent value to set the state of the text area back to empty or ‘ ‘ by using the TinyMCE set content API to target the currently active editor, and set the content to empty:

setContent(window.tinymce.activeEditor.setContent(""));
  1. Scroll down to the articles.map content, and change the <p> tags surrounding the {article.content} into <div> tags:

{
  articles.map((article, index) => (
    <li key={index}>
                 <h3>{article.title}</h3>
                 <div>{article.content}</div>
               
    </li>
  ));
}
  1. Save the changes, and then test out creating an article again:

 

Article creation working with enriched react textarea

 

And with this complete, you’ve successfully created an enriched, React textarea with the TinyMCE integration (well done!).

How to autoresize the textarea in React

Instead of finding a way within the React files to facilitate an automatic size-change of the textarea,  you can configure the TinyMCE the Autoresize plugin. 

  1. Add this plugin to the TinyMCE plugin list in the React textarea demo:

init= {{
    height: 300,
    plugins: ['autoresize a11ychecker advcode advlist advtable anchor…
  1. Include the max_height option, and set it to 400:
init= {{
    height: 300,
    plugins: ['autoresize a11ychecker advcode advlist advtable anchor'],
    max_height: 400
  1. Save the changes

Now, the React textarea won’t expand past 400px when large amounts of content are added to the editor.

How to make a text input noneditable with React

There’s two methods to get this done.

  1. If you’d like to set up some specific content in the editor to be non-editable, set up the TinyMCE non-editable class, and then use a particular method such as the initialValue configuration to establish the some content as non editable:

 <Editor 
          tinymceScriptSrc={process.env.PUBLIC_URL + '/tinymce/tinymce.min.js'}
          apiKey='your-api-key'
          initialValue='<p class=noneditable>This cannot be edited</p>'
          init= {{
   …
            noneditable_class: 'noneditable'
          }}
        />
  1. The second method prevents editing within the editor altogether with the TinyMCE react disabled prop. Using this prop will make the entire editor non-editable: 

        <Editor 
          tinymceScriptSrc={process.env.PUBLIC_URL + '/tinymce/tinymce.min.js'}
          disabled={true}

How to handle textarea onChange in React

While the demo made use of the React dangerouslysetinnerHTML for expediency, this is not an advisable solution for React apps in production.  Converting a string to HTML to be executed and rendered by the browser brings risk alongside it (allowing cross-site scripting (XSS) attacks). The React method passes objects with the __html key as a reminder of the danger involved.

As an alternative – particularly if you’re including TinyMCE in your React app to work as a controlled component where the data is handled within the component – check on the TinyMCE editorOnChange prop. It stores the current value of the TinyMCE editor as HTML.

Moving forward with the React textarea

The main resource to look through for more information on setting up and optimizing an enriched React textarea with TinyMCE is the TinyMCE React technical reference. It contains a complete list of the available props for your React app. 

Other useful articles on the TinyMCE blog are:

Interested how get rich text editing opportunities for the textarea of a different framework? We have guides to help you with this: learn how to configure and work with enriched

Contact us if you have any further questions about building your app with TinyMCE.

TinyMCEReactIntegrationJavascript
byJoe Robinson

Technical and creative writer, editor, and a TinyMCE advocate. An enthusiast for teamwork, open source software projects, and baking. Can often be found puzzling over obscure history, cryptic words, and lucid writing.

Related Articles

  • How-to Use TinyMCEFeb 29th, 2024

    Mastering Javascript font color changes in TinyMCE

Join 100,000+ developers who get regular tips & updates from the Tiny team.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.