Support for React-quill node package

Hello everyone,

have anyone tried to implement react-quill node package (https://www.npmjs.com/package/react-quill) in Frontity project? I need it in mine but have no clue how to implement it. Am not even sure if it’s possible because it uses classes.

@luisherranz could you provide some info on using class-based React components with Frontity, i.e. whether it’s possible and if so how it can be done? Thanks.

The thing is, I kind of managed the package to work (without the use of class-based React components). The problem I have, though, is that whenever I refresh the page, I get the following error: Reference error: document is not defined and everything breaks.

If I don’t refresh the page, everything works (close to) normally.

Hey @tix, could it be because the quill library is trying to access window.document in the server during server-side rendering? I mean in the node.js server, where window.document doesn’t exist.

Maybe the ReactQuill component only works in the browser, try checking the state.frontity.rendering property before rendering it:

const Quill = ({ actions, state }) => {
  // ...
  return (
    <>
      {state.frontity.rendering === "csr" && (
        <ReactQuill theme="snow" value={value} onChange={setValue} />
      )}
    </>
  );
};

BTW, @mburridge I failed trying to find documentation about that property and others exposed by Frontity (these ones). Is it something you already have in the radar? Should I open an issue in the docs repo?

1 Like

Hey @David,

I tried with that code but still get the same problem…

Hey @tix,

Thanks for posting this. @David’s suggestion should be working but I believe react-quill has side-effects – meaning when imported it executes some code.

So, you should approach it differently and lazy load it. That means using a dynamic import via loadable. Link.

import { loadable } from 'frontity';

const LazyComponent = loadable(() => import("package"));

I went ahead and created this CodeSandbox for you https://codesandbox.io/s/awesome-leavitt-tkjdo?file=/packages/quill-theme/src/components/editor.js. As you can see it works.

By using dynamic import you also get the benefit of code splitting, meaning the package won’t exist in the JavaScript bundles for other pages.

Let us know if this helps you and solves your issue.

2 Likes

Hi @David, yes please open an issue and we’ll attend to that. Thanks.

Hey @christianbote,

thanks a lot! The code from CodeSandbox works well. I also tried like this:

const Quill = () => {
  const [reactQuill, setReactQuill] = useState();
  const [value, setValue] = useState("");

  useEffect(() => {
    if (typeof window !== "undefined") {
      import("react-quill").then((mod) => {
        setReactQuill(mod);
      });
    }
  }, []);

  if (reactQuill) {
    return (
      <div>
        <p>Value: {value}</p>
        <reactQuill.default theme="snow" value={value} onChange={setValue} />
      </div>
    );
  }

  return null;
};
export default connect(Quill);

(I am calling styles for this package in index.js) and it also works. Is that way also okay or should it be strictly like how you did it?

I haven’t noticed that you used loadable() function here, though… Is it because it’s already inside useEffect() function?

Finally, can you (or someone else) please explain, how to know if you would have to use the dynamic import approach for a specific react package or not?

Hey @tix I’ve updated my comment and the linked codesandbox after you’ve already seen it, I believe. Both methods work, but with loadable you don’t have to do the useEffect and useState ‘dance’.

Regarding lazy loading via dynamic imports, it’s really when you see those kind of errors that document or window is undefined when this is the case. Also as a rule of best practices when you have a large package it’s always better to split the logic between pages, in order for those pages that are not using it to not have to load unnecessary scripts.

1 Like

Yes, that was the case. With loadable() it’s also working just fine. Seems like an even easier approach. Also, thanks a lot for the explanation regarding the lazy loading.

Maybe (if it’s not too much to ask), could also someone help me to figure out how could I call this getText() function that this package includes (https://quilljs.com/docs/api/#gettext). The thing is, I have to get the text/content from React Quill Editor which is stored in some API that I am fetching.