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/).