Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-quilljs and reactjs-popup don't work together

I'm using react-quilljs and reactjs-popup together and can't get the quill-based editor to show in my modal dialog. I can use the editor on the main page with no issues but it will not work on the popup.

I have the expected imports:

import React from "react";
import Popup from "reactjs-popup";
import "reactjs-popup/dist/index.css";
import { useQuill } from "react-quilljs";

And my component looks something like this:

const NewIdeaDialog = ({ showNewIdea }) => {
  const { quill, quillRef } = useQuill();
  return (
    <Popup open={showNewIdea} nested>
      <div>
        <form action="" method="">
          <label for="IdeaDetails">Details</label>
          <div style={{ width: 500, height: 300 }} id="IdeaDetails">
            <div ref={quillRef} />
          </div>
        </form>
      </div>
    </Popup>
  );
}

When I set showNewIdea to true in the parent component the popup is displayed, as expected, but the quill editor is completely missing. It renders the #IdeaDetails div and a child that is <div></div> and that's all. The child div is completely empty and devoid of styling.

Am I missing something that will make this work? I can't find any similar issues listed on the web for this problem.

like image 895
Software Engineer Avatar asked Jul 18 '21 18:07

Software Engineer


1 Answers

It's working just right

enter image description here

with qill css too

import 'quill/dist/quill.snow.css';

The same code is working perfectly

import React from "react";
import Popup from "reactjs-popup";
import "reactjs-popup/dist/index.css";
import { useQuill } from "react-quilljs";
import './App.css';
import 'quill/dist/quill.snow.css'; // <<<====

function App({showNewIdea}) {
  const { quill, quillRef } = useQuill();
  return (
    <Popup open={true} nested> {/* <======= set to true */}
      <div>
        <form action="" method="">
          <label for="IdeaDetails">Details</label>
          <div style={{ width: 500, height: 300 }} id="IdeaDetails">
            <div ref={quillRef} />
          </div>
        </form>
      </div>
    </Popup>
  );
}

export default App;

Wait it worked because show is true

The code above work because the popup show, is set to true!

So if the Popup state change it will not work!

Solution: Something that works

As @Software Engineer! Mentionned in the comment! He asked the author of the library! you can check here

A solution that works! Is to wrap the elements that go within the Popup! On there own component! And initiate quil there! Throught the useQuill hook!

import "reactjs-popup/dist/index.css";
import "quill/dist/quill.snow.css"; // Add css for snow theme
// or import 'quill/dist/quill.bubble.css'; // Add css for bubble theme

export default () => {
  const [showNewIdea, setShowNewIdea] = useState(false);

  const togglePopup = () => setShowNewIdea(!showNewIdea);

  return (
    <div>
      <input type="button" value="open" onClick={togglePopup} />
      <Popup open={showNewIdea} nested>
        <NewIdeaDialog />
      </Popup>
    </div>
  );
};

const NewIdeaDialog = () => {
  const { quillRef } = useQuill();
  return (
    <div>
      <form action="" method="" style={{ width: "100%", height: "100%" }}>
        <label for="IdeaDetails">Details</label>
        <div style={{ width: "100%", height: "100%" }} id="IdeaDetails">
          <div ref={quillRef} />
        </div>
      </form>
    </div>
  );
};

You can check the playground here! That include to debug! And undestand why!

What was the problem and what we can learn from this

This answer is not finished! This section will be updated later! (i'll share both some observations! And explain the why) (you may check later)

Quill hook function

export const useQuill = (options: QuillOptionsStatic | undefined = { theme, modules, formats }) => {
  const quillRef: RefObject<any> = useRef();

  const [isLoaded, setIsLoaded] = useState(false);
  const [obj, setObj] = useState({
    Quill: undefined as any | undefined,
    quillRef,
    quill: undefined as Quill | undefined,
    editorRef: quillRef,
    editor: undefined as Quill | undefined,
  });

  useEffect(() => {
    if (!obj.Quill) { obj.Quill = require('quill') as Quill; }
    if (obj.Quill && !obj.quill && quillRef && quillRef.current && isLoaded) {
      const opts = assign(options, {
        modules: assign(modules, options.modules),
        formats: options.formats || formats,
        theme: options.theme || theme,
      })
      const quill = new obj.Quill(quillRef.current, opts);

      setObj(assign(assign({}, obj), { quill, editor: quill }));
    }
    setIsLoaded(true);
  }, [obj.Quill]);

  return obj;
};

First implementation

enter image description here

Separate component

enter image description here

Expect update for the explanation of how and why! And the details!

like image 169
Mohamed Allal Avatar answered Oct 26 '22 21:10

Mohamed Allal