react-quill-new

repository·main·Indexed 41 days ago

https://github.com/vaguelyserious/react-quill

A React component wrapper around Quill 2.x and 1.x that manages the lifecycle, state, and bridge between React and the Quill rich text editor. It supports controlled and uncontrolled modes, provides an UnprivilegedEditor proxy in callbacks for safe state access, and allows direct access to the underlying Quill instance via ref.getEditor() or the static Quill property.

Tokens
2.8K
Snippets
5
Records
16
Agent score
51%

What's inside react-quill-new

  1. How to use Deltas for state management

    main

    When working with Quill Deltas, follow these rules to avoid common state synchronization issues:

    • Avoid Infinite Loops: Do not feed the delta argument received from the onChange event directly back into the value prop.
    • Correct Delta Retrieval: If you want to store or manage the editor state as a Delta, use editor.getContents() instead of relying on the onChange argument.
  2. Deploy the demo to Vercel

    main

    The demo is a static site located in apps/demo/public. It relies on the built browser bundle from packages/react-quill-new and copies necessary assets into public/assets during the build process. To deploy this demo to Vercel, use the following project settings:

    Recommended Vercel project settings:
    
    - Root Directory: apps/demo
    - Install Command: pnpm install --frozen-lockfile
    - Build Command: pnpm -w build
    - Output Directory: public
  3. Quick start with ReactQuill

    main

    To use ReactQuill in a React component, import the component and its CSS theme (e.g., snow). You can implement it as a controlled component using value and onChange props.

    import { useState } from 'react';
    import ReactQuill from 'react-quill-new';
    import 'react-quill-new/dist/quill.snow.css';
    
    export function Editor() {
      const [value, setValue] = useState('');
      return <ReactQuill theme="snow" value={value} onChange={setValue} />;
    }
  4. Integration considerations for React 18/19 and SSR

    main

    If you are integrating react-quill-new into a modern React application (v18 or v19) or using Server-Side Rendering (SSR) like Next.js, keep the following in mind:

    React 18/19 and StrictMode

    • StrictMode Double-Invocation: Be prepared for components to mount/unmount twice in development, which can trigger editor re-initialization.
    • Lifecycle Timing: Ensure that the DOM node is fully available before Quill attempts to initialize to avoid "Invalid Quill container" errors.

    SSR and Next.js

    • Window/Document Availability: Since Quill requires a browser environment, you must use dynamic imports or ensure the component only renders on the client side to avoid document/window is not defined errors.
    • Hydration: Be cautious of hydration mismatches when the server-rendered HTML differs from the client-side Quill-generated content.
  5. Use ReactQuill via Browser Bundle (no build step)

    main

    For environments without a build step, you can use the provided browser bundle.

    1. CSS: Include quill.snow.css or quill.bubble.css from the package.
    2. JS: Include React and ReactDOM (UMD) via script tags, then include dist/react-quill.js.

    The bundle exposes the following on the window object:

    • window.ReactQuill.default: The React component.
    • window.ReactQuill.Quill: The bundled Quill constructor.
  6. Use the UnprivilegedEditor proxy in callbacks

    main

    In event callbacks like onChange, onFocus, and onBlur, the editor argument is provided as an UnprivilegedEditor. This is a read-only proxy designed to prevent accidental state mutations within the callback.

    Supported methods on UnprivilegedEditor:

    • getHTML(): Returns the editor's HTML.
    • getSemanticHTML(): Returns the editor's semantic HTML.
    • getLength(): Returns the length of the editor content.
    • getText(): Returns the plain text content.
    • getContents(): Returns the Quill Delta.
    • getSelection(): Returns the current selection range.
    • getBounds(): Returns the bounds of the selection.
  7. Known issues and regression risks in react-quill-new

    main

    When using react-quill-new, be aware of the following known issue clusters that may affect your implementation:

    Editor Lifecycle and Initialization

    • Invalid Quill container: Errors occurring during React 19 lifecycles or when modules/options are mutated, often due to ref timing or initialization against a missing DOM node.
    • Focus Loss: Using controlled values via onChange can sometimes cause the editor to lose focus due to re-renders resetting selection.
    • Duplicate Toolbars: Issues where toolbars appear twice, particularly noted in Next.js 15 and React 19 environments.
    • Multi-instance interference: Potential for cross-instance DOM/ID collisions or shared state when multiple editors are present on one page.

    Content and Formatting

    • List Behavior: Potential issues with long list numbering (e.g., Roman numerals > 16 or decimals > 99) and alignment loss (ql-align-*) during copy/paste.
    • Clipboard/Paste: Issues with whitespace preservation, multiple spaces collapsing on paste, and tab/indentation behavior.
    • Custom Toolbars: Potential for partial breakage in heading toggles, undoing formatting, or list indentation when using custom toolbar configurations.

    TypeScript and API

    • Typing for Blots: Importing Blot via Quill.import("blots/inline") may return unknown in certain TypeScript configurations.
    • Ref Forwarding: Ensure you are using the component in a way that supports ref attributes, as some older patterns may have typing issues.
  8. Configure ReactQuillProps

    main

    The ReactQuillProps interface defines the configuration available for the component.

    PropTypeDescription
    valuestring | DeltaStaticThe current content of the editor (Controlled mode).
    defaultValuestring | DeltaStaticThe initial content of the editor (Uncontrolled mode).
    themestringThe Quill theme to use (e.g., 'snow'). Defaults to 'snow'.
    modulesQuillOptions['modules']Configuration for Quill modules (e.g., toolbar, keyboard).
    formatsstring[]List of allowed formats.
    readOnlybooleanIf true, the editor is disabled. Defaults to false.
    placeholderstringPlaceholder text for the editor.
    onChange(value: string, delta: DeltaStatic, source: EmitterSource, editor: UnprivilegedEditor) => voidCallback triggered on content changes.
    onChangeSelection(selection: Range, source: EmitterSource, editor: UnprivilegedEditor) => voidCallback triggered when the text selection changes.
    onFocus(selection: Range, source: EmitterSource, editor: UnprivilegedEditor) => voidCallback triggered when the editor gains focus.
    onBlur(previousSelection: Range, source: EmitterSource, editor: UnprivilegedEditor) => voidCallback triggered when the editor loses focus.
    boundsstring | HTMLElementThe element that bounds the tooltip/popovers.
    classNamestringCSS class applied to the outer container.
    styleReact.CSSPropertiesInline styles for the outer container.
    idstringThe ID for the container element.
    tabIndexnumberThe tab index for the editor.
    preserveWhitespacebooleanIf true, renders a <pre> instead of a <div> for the editing area.
  9. Use the ReactQuill component

    main

    The ReactQuill component is the primary interface for integrating the Quill editor into a React application. It supports both controlled and uncontrolled modes using the value or defaultValue props.

    Important Usage Notes:

    • Value Types: The value prop can be either a string (HTML) or a DeltaStatic object. If you use Deltas, ensure you use editor.getContents() to retrieve them, rather than passing the delta from onChange directly back into the value prop, which can cause infinite loops.
    • Editing Area: By default, the component renders a <div> as the editing area. If you provide children, they must be a single React element. Note that <textarea> is not supported as a child; use a <div> instead.
    • Regeneration: Certain props like modules, formats, bounds, theme, and children are considered "dirty props." Changing them will cause the entire Quill editor instance to be destroyed and re-instantiated.
    import ReactQuill from 'react-quill';
    
    // Controlled example
    <ReactQuill 
      value="<p>Hello World</p>" 
      onChange={(content, delta, source, editor) => {
        console.log(content);
      }} 
    />
    
    // Uncontrolled example
    <ReactQuill 
      defaultValue="<p>Initial content</p>" 
    />