6

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.

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
Software Engineer
  • 15,457
  • 7
  • 74
  • 102

1 Answers1

3

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!

Mohamed Allal
  • 17,920
  • 5
  • 94
  • 97
  • Thanks for this. I already had the CSS but forgot to list it here. I'll experiment some more, thanks for the confirmation. If this is working for you then I'm wrong about the cause and I'll mark your answer as right. V.helpful, saves me barking up the wrong tree, thx – Software Engineer Jul 19 '21 at 01:29
  • Thanks bro! i would like to know what the problem was! Once you finish you may let me know so i update the answer to reflect it – Mohamed Allal Jul 19 '21 at 21:40
  • 1
    1: see comment on my question. 2. I think that quill doesn't like to be created in a hidden state. The difference between your code and mine is that you have `open={true}`. If I do that then it works for me too but if I start with `show={false}` then change that to `true` then quill remains hidden. – Software Engineer Jul 20 '21 at 20:00
  • Thank you sir! I updated temporally the answer to reflect the solution above! i couldn't figure out the problem form a first look! i'll update the answer just as i get done! I made some observations! The quillRef Changing only twice on consecutive re-render and also to a null value! I'll debug to see exactly what's happening! – Mohamed Allal Jul 21 '21 at 20:58
  • A little thing for label => `for` attribute should be `htmlFor` https://reactjs.org/docs/dom-elements.html#htmlfor – Mohamed Allal Jul 21 '21 at 21:14