Self-hosting TinyMCE in React

This guide shows how to self-host TinyMCE in a React application using the TinyMCE React component.

Prerequisites

This procedure requires Node.js (and NPM).

Procedure

  1. Use Vite and React SWC to create a new React project named tinymce-react-demo.

    # NPM 7+, extra double-dash is needed
    npm create vite@5 tinymce-react-demo -- --template react-swc
  2. Go to the project directory and install @tinymce/tinymce-react

    cd tinymce-react-demo && npm install @tinymce/tinymce-react
  3. Install the tinymce package.

    npm install tinymce
  4. Install fs-extra as a development dependency:

    npm install -D fs-extra
  5. Setup a postinstall script to copy TinyMCE to public directory, which automatically makes TinyMCE and other components available as static assets after each installation.

    Add postinstall.js file.
    import fse from 'fs-extra';
    import path from 'path';
    
    const topDir = import.meta.dirname;
    fse.emptyDirSync(path.join(topDir, 'public', 'tinymce'));
    fse.copySync(path.join(topDir, 'node_modules', 'tinymce'), path.join(topDir, 'public', 'tinymce'), { overwrite: true });
    Update postinstall target in package.json to run the postinstall.js script.
    {
      // ... other content omitted for brevity ...
      "scripts": {
        // ... other scripts omitted for brevity ...
        "postinstall": "node ./postinstall.js"
      }
    }
  6. Exclude public/tinymce from Git tracking

    # ... other rules omitted for brevity ...
    /public/tinymce/
  7. In this instance, run the postinstall to copy TinyMCE to the public directory.

    npm run postinstall
  8. Update App.jsx to include Editor component. Note: tinymceSrcScript references to the public tinymce using absolute root path.

    import { useRef } from 'react';
    import { Editor } from '@tinymce/tinymce-react';
    import './App.css';
    
    export default function App() {
      const editorRef = useRef(null);
      const log = () => {
        if (editorRef.current) {
          console.log(editorRef.current.getContent());
        }
      };
      return (
        <>
          <Editor
            tinymceScriptSrc='/tinymce/tinymce.min.js'
            licenseKey='gpl'
            onInit={(_evt, editor) => editorRef.current = editor}
            initialValue='<p>This is the initial content of the editor.</p>'
            init={{
                height: 500,
                menubar: false,
                plugins: [
                  'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
                  'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
                  'insertdatetime', 'media', 'table', 'preview', 'help', 'wordcount'
                ],
                toolbar: 'undo redo | blocks | ' +
                  'bold italic forecolor | alignleft aligncenter ' +
                  'alignright alignjustify | bullist numlist outdent indent | ' +
                  'removeformat | help',
                content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
            }}
          />
          <button onClick={log}>Log editor content</button>
        </>
      );
    }
  9. Run the development server to test the application:

    npm run dev

Other resources