reactjsreact-hook-formdraft-js-plugins

Multiple draft-js-plugins editors on the same page don't work


I'm trying to use multiple rich text editors in a React form. I built the editor component using draft-js and also I integrated the inline toolbar from draft-js-plugins. Because this is a react-hook-form I wrapped the editor inside a Controller component.

The problem I have is that the InlineToolbar is displayed only for the last editor component in page.

Based on the draft-js-plugins documentation the initialization of the toolbar should happen outside the component so this is what I did:

const inlineToolbarPlugin = createInlineToolbarPlugin();
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [inlineToolbarPlugin];

function RichTextEditor({ control, name }) {
  return (
    <div>
      <Controller
        name={name}
        control={control}
        render={({ field: { value, onChange } }) => {
          const newValue = value || EditorState.createEmpty();
          return (
            <>
              <Editor
                editorState={newValue}
                onChange={onChange}
                plugins={plugins}
              />
              <InlineToolbar />
            </>
          );
        }}
      />
    </div>
  );
}

A complete CodeSandbox example here: CodeSandbox link


Solution

  • Each editor get's its own plugins.

    You can solve this issue ether by creating different plugin for each editor instance and pass them to the editor OR with create a function for creating a plugin inside the editor component and every time we init a editor we create a new plugin instance

    So, this is the first solution:

      const inlineToolbarPlugin1 = createInlineToolbarPlugin();
      const { InlineToolbar:Tool1 } = inlineToolbarPlugin1;
    
      const inlineToolbarPlugin2 = createInlineToolbarPlugin();
      const { InlineToolbar:Tool2 } = inlineToolbarPlugin2;
    

    And pass them into your custom editor components.


    Second solution:

      import React from "react";
    import { Controller } from "react-hook-form";
    import { EditorState } from "draft-js";
    import PropTypes from "prop-types";
    import Editor from "@draft-js-plugins/editor";
    import createInlineToolbarPlugin from "@draft-js-plugins/inline-toolbar";
    import "@draft-js-plugins/inline-toolbar/lib/plugin.css";
    import "draft-js/dist/Draft.css";
    
    const createtoolbarplugin = () => {
      const InlineToolbarPlugin = createInlineToolbarPlugin();
      const InlineToolbar = InlineToolbarPlugin.InlineToolbar;
      return {
        InlineToolbarPlugin,
        InlineToolbar
      };
    };
    
    function AnotherRichTextEditor({ control, aName }) {
      const [{ InlineToolbarPlugin, InlineToolbar }] = React.useState(() => {
        const { InlineToolbar, InlineToolbarPlugin } = createtoolbarplugin();
        return {
          InlineToolbarPlugin,
          InlineToolbar
        };
      });
    
      return (
        <div
          style={{
            border: "1px solid #ccc",
            minHeight: 30,
            padding: 10
          }}
        >
          <Controller
            name={aName}
            control={control}
            render={({ field: { value, onChange } }) => {
              const newValue = value || EditorState.createEmpty();
              return (
                <>
                  <Editor
                    editorState={newValue}
                    onChange={onChange}
                    plugins={[InlineToolbarPlugin]}
                  />
                  <InlineToolbar />
                </>
              );
            }}
          />
        </div>
      );
    }
    
    AnotherRichTextEditor.propTypes = {
      control: PropTypes.object,
      aName: PropTypes.string
    };
    
    export default AnotherRichTextEditor;
    
    

    Hope That's help