React editor

React rich text editor.

Add WYSIWYG editing to your React app. Start with the component, or build your own toolbar with the hook.

Details

Drop in the controlled <RichTextEditor> component for a full toolbar in one line, or build your own UI with the useRichTextEditor hook. Add content editing to your CMS, knowledge base, or business application, then save the HTML through your own API.

Paid licenses start at $129 for one domain, with perpetual use of your licensed version and one year of updates. AI provider usage, optional hosting, and future update renewals are separate.

React focus

Built to respect React’s ownership model.

Component or hookControlled value/onChange component, or a headless hook whose state re-renders your own buttons on every selection change.
Typed imperative handleRichTextEditorReactHandle exposes getHTMLCode, getJSON/setJSON, focus, statistics, outline, and the plugin surfaces.
StrictMode & SSR safeMount/unmount is idempotent and teardown calls editor.destroy(), so React 18 StrictMode double-invoke and App Router client components just work.
Sony
Intel
Nokia
Siemens
IBM
Microsoft

Get your first React editor working

  1. Run the sample.

    Download the React starter, extract it, then run npm ci and npm run dev.

  2. Check your content.

    Type or paste in the editor and watch the HTML output update. This starter does not save content.

  3. Connect your app.

    Read current HTML at submit, then add your own save API. Set up image uploads separately. Troubleshoot image uploads.

The starter uses the npm React binding shown below. For the full trial package and its browser-local save example, follow the React trial guide. Get integration help with your React version and a minimal example.

Cursor moves or edits disappear? Troubleshoot React editor state and remounting.

Install once, pick your integration style

One npm package ships the engine, the React bindings, and the plugin bundle. React 18+ is a peer dependency.

npm install @richscripts/richtexteditor

In npm version 2.16.0, TypeScript projects that check dependency declarations may encounter an onError type conflict. Updated declarations are being prepared; contact support if this blocks your integration.

Option 1 — the drop-in component

A controlled component with the familiar value/onChange contract. Pass any editor option through config — toolbar presets, height, upload endpoints, AI settings.

import { useState } from "react";
import { RichTextEditor } from "@richscripts/richtexteditor/react";

export function Composer() {
  const [html, setHtml] = useState("<p>Draft your update...</p>");
  return <RichTextEditor value={html} valueFormat="html"
    onChange={(next) => { if (typeof next === "string") setHtml(next); }}
    config={{ height: 400 }} />;
}

Option 2 — bring your own UI with the hook

The hook works in JavaScript. In npm version 2.16.0 its TypeScript declarations are incomplete; TypeScript projects can use the component above until updated declarations are published.

useRichTextEditor returns the live editor plus a state snapshot (bold, h2, canUndo, ...) that re-renders your buttons as the selection moves — the pattern Tiptap and Lexical users expect, without giving up the built-in plugins. Use onMouseDown + preventDefaultso your buttons don’t steal focus from the editor.

import { useRichTextEditor, EditorContent } from "@richscripts/richtexteditor/react";

export function Editor() {
  const editor = useRichTextEditor({ value: "<p>Hello</p>" });
  return (
    <>
      <button
        type="button" disabled={!editor.editor} aria-pressed={!!editor.state.bold}
        onPointerDown={(e) => e.preventDefault()}
        onClick={() => editor.run("bold")}
        className={editor.state.bold ? "is-active" : ""}
      >Bold</button>
      <button type="button" disabled={!editor.editor || !editor.state.canUndo}
        onPointerDown={(e) => e.preventDefault()}
        onClick={() => editor.run("undo")}
      >Undo</button>

      <EditorContent editor={editor} />
    </>
  );
}

Reading and writing content imperatively

Attach a ref to get a typed RichTextEditorReactHandle: HTML in/out, the structured JSON document model, text statistics, document outline, and accessors for AI Toolkit, comments, tracked changes, and collaboration.

import { useRef } from "react";
import { RichTextEditor } from "@richscripts/richtexteditor/react";
import type { RichTextEditorReactHandle } from "@richscripts/richtexteditor/react";

export function Form() {
  const editorRef = useRef<RichTextEditorReactHandle>(null);

  const submit = () => {
    const html = editorRef.current?.getHTMLCode() ?? "";
    const json = editorRef.current?.getJSON();     // structured document
    // send html / json to your API ...
  };

  return (
    <>
      <RichTextEditor ref={editorRef} defaultValue="<p></p>" />
      <button onClick={submit}>Save</button>
    </>
  );
}

Next.js and server rendering

The editor is a client-side surface. In the App Router, wrap it in a "use client" component; this very site is a Next.js app running the editor on its demo pages. For rendering saved content on the server, the package’s server entry converts the structured JSON to static HTML without a DOM.

"use client";
// The editor renders into a live DOM, so in Next.js App Router keep it in a
// client component. Server components can pass initial HTML down as a prop.
import { RichTextEditor } from "@richscripts/richtexteditor/react";

export default function EditorClient({ initialHtml }: { initialHtml: string }) {
  return <RichTextEditor defaultValue={initialHtml} />;
}

Why teams pick it over building on a framework-only editor

  • Everything is included: AI Toolkit (bring your own key), per-node Yjs CRDT collaboration, tracked changes, comments, and revision history are part of the license — not premium add-ons.
  • Clean HTML out: the output is publish-ready markup, plus a structured JSON model when you want validation or server rendering.
  • Perpetual license from $129: no per-seat AI pricing and no subscription; see pricing and the Tiptap / Lexical comparisons.

Guides for React, JavaScript: uploads, gallery and files

Tested server code for each step, one problem per page.

All React guides

Using something else? There are matching guides for Next.js, Vue, Angular, Svelte, Blazor, ASP.NET Core, PHP, and plain JavaScript.