Next.js setup

Redactor works in Next.js. Import the editor into a React component, create it in useEffect, and call destroy() on cleanup.

The counter plugin is included only as an example of how to load and enable a plugin — replace it with any plugins you need.

Copy Redactor into the project (for example next to the component):

components/
  redactor.esm.min.js
  redactor.css
  plugins/
    counter.js
  RedactorJS.js

Editor component#

// components/RedactorJS.js
'use client';

import { useEffect, useRef } from 'react';
import './redactor.css';
import Redactor from './redactor.esm.min.js';
import './plugins/counter.js';

export default function RedactorJS() {
    const textAreaRef = useRef(null);

    useEffect(() => {
        if (!textAreaRef.current) return;

        const editor = Redactor(textAreaRef.current, {
            plugins: ['counter'],
            content: '<p>Hello World!</p>'
        });

        return () => {
            editor?.destroy();
        };
    }, []);

    return <textarea ref={textAreaRef} />;
}

Use on a page#

// app/page.js
'use client';

import RedactorJS from '../components/RedactorJS';

export default function Page() {
    return (
        <div>
            <RedactorJS />
        </div>
    );
}

Make sure the path to the component is correct for your folder layout.

Dynamic import#

Redactor uses browser APIs (window, document). Server rendering can fail. Load the editor only on the client with dynamic and ssr: false:

// app/page.js
'use client';

import dynamic from 'next/dynamic';

const RedactorJS = dynamic(() => import('../components/RedactorJS'), {
    ssr: false
});

export default function Page() {
    return (
        <div>
            <RedactorJS />
        </div>
    );
}

The same dynamic(…, { ssr: false }) pattern works with the Pages Router (pages/).