react-quill icon indicating copy to clipboard operation
react-quill copied to clipboard

React Quill removing all formatting and html tags from values when using used from a reopened modal

Open Johnrobmiller opened this issue 3 years ago • 11 comments

I am unable to provide code that replicates this, but here are the instructions:

  • In a Next.js project, create a modal using the Headless UI "Dialogue" component
  • dynamically import React Quill to be used within that modal for the inputs of a form.
  • Store the form value states in a React component using useState() and pass in the form values to Quill inputs as the defaultValue.
  • Set the state of the value using React Quill's onChange prop.
  • In localhost, type something into react quill (anything with formatting, e.g., a list)
  • close and reopen the modal
  • all formatting will be gone, and a console.log of the value will show that all html tags have been removed.

Speculation about the cause: It might have something to do with some race condition when we dynamically import the ReactQuill input into the modal. However, this is just speculation.

Hacky workaround: if I have a "firstRender" state, set it to true initially, set it to false using useEffect(..., []), but then render null on the first render by checking if "firstRender" is true, then the bug will no longer occur.

Johnrobmiller avatar Jun 26 '22 21:06 Johnrobmiller

same :(

keilestone avatar Aug 12 '22 05:08 keilestone

the same bug, The value auto remove some tags html.

thuongbui1 avatar Oct 19 '22 03:10 thuongbui1

@Johnrobmiller thanks for providing this workaround.

jeremylaiyt avatar Nov 05 '22 17:11 jeremylaiyt

This is for the people who did not have luck with delaying by one render as suggested. This issue might be happening due to the modal opening animation. If we set the rich text to quill editor before it appears on screen, it may calculate the new lines at the wrong time.

In my case, the modal is animating from zero size to full size, and I am setting the rich text at zero size. So I removed the animation and the problem was solved. If you don't want to remove the animation, listen to the animation ending then set the value to quill editor.

Sateesh2 avatar Mar 28 '23 17:03 Sateesh2

Something similar to this happens to me using CRA and Ant Design in a Modal component: react-quill was removing tags from the initial value that I passed to it. The workaround proposed here worked well for me. thanks @Johnrobmiller

import { Modal, ModalProps} from 'antd';
import { FC, useEffect, useState } from 'react';
import ReactQuill, { ReactQuillProps } from 'react-quill';

const DescriptionModal: FC<
  Omit<ModalProps, 'onOk'> & {
    onOk: (html: string) => void;
    initialValue?: string;
  }
> = ({ onOk, initialValue='', ...modalProps }) => {
 
  const [isInitialRender, setIsInitialRender] = useState(true);

  const [html, setHtml] = useState<string>(initialValue || '');

  useEffect(() => setIsInitialRender(false), []);

  return (
    <Modal
      {...}
      {...modalProps}
      onOk={() => onOk(html)}
    >
      {!isInitialRender && (
        <>
          {...}
            <ReactQuill {...} value={html} onChange={(v) => setHtml(v)} />
          {...}
        </>
      )}
    </Modal>
  );
};

export default ServiceDescriptionModal;

jjavierdguezas avatar Jul 07 '23 13:07 jjavierdguezas

Not sure if this is the best answer, but I was not having luck by delaying the render.

I use the source argument, which is the string value "user" if the on change event comes from the user typing. This way I only execute the on change event as intended preventing the stripping of the html tags.

<ReactQuill
  // ... your props
  onChange={(value, _delta, source) => {
    if (source === "user") form.setFieldValue(field.name, value);
   }}
/>

McleanWorkshield avatar Sep 06 '23 16:09 McleanWorkshield

@jjavierdguezas Comment works for CRA and Ant Design in a Modal. I have debugged it, and I am not sure why it is like this when the component gets mounted and we are assigning some predefined HTML code to the Quill editor value the onChange function gets triggered automatically, but when the value reaches to first time onChange function it already has stripped some of the HTML tags from it. Below code I have added in my example from @jjavierdguezas code which works for me.

const DescriptionModal = (props) => {
const { html } = props; 

const [isInitialRender, setIsInitialRender] = useState(true);
const [emailBodyValue, setEmailBodyValue] = useState('');

 const setHtml = (content, delta, source, editor) => {
        if(source === "user") {
            setEmailBodyValue(editor.getHTML());
        }
    };

return (
    <Modal
{...modalProps}
    >
      {!isInitialRender && (
        <>
          {...}
            <ReactQuill {...} value={html} onChange={setHtml} />
          {...}
        </>
      )}
    </Modal>
  );
};

export default DescriptionModal;

vishwakarmanikhil avatar Dec 26 '23 17:12 vishwakarmanikhil