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.
-
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...
-
Change into the new project directory:
cd cms-demo
-
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;
-
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;
}
-
To test out the app, use the npm run command, which automatically opens the demo running a React Textarea:
npm run start
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:
-
Stop the demo running with Ctrl + c, and then Install TinyMCE through npm:
npm install --save tinymce @tinymce/tinymce-react fs-extra
-
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 }
);
-
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"
},
-
Modify the .gitignore file, adding the following line:
#tinymce
/public/tinymce/
-
Copy TinyMCE to the public/ directory by running the postinstall script:
npm run postinstall
-
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";
-
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.
-
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= {{
-
Save the changes, and then restart the React demo if needed:
npm start
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:
- Disable the React textarea
- 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:
-
Inside the addArticle function, set up a new constant called “StringtoHTML”:
const addArticle = () => {
const stringToHTML =
-
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
-
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
-
Remove “content” from the function App() list of constants as it is no longer needed.
function App() {
…
const [setContent] = useState('');
-
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(""));
-
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>
));
}
-
Save the changes, and then test out creating an article again:
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.
-
Add this plugin to the TinyMCE plugin list in the React textarea demo:
init= {{
height: 300,
plugins: ['autoresize a11ychecker advcode advlist advtable anchor…
- Include the max_height option, and set it to 400:
init= {{
height: 300,
plugins: ['autoresize a11ychecker advcode advlist advtable anchor'],
max_height: 400
-
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.
-
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'
}}
/>
-
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:
- Emulating a document editor with React and TinyMCE
- A guide to optimizing React performance
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.