react-quill
react-quill copied to clipboard
React Quill removing all formatting and html tags from values when using used from a reopened modal
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.
same :(
the same bug, The value auto remove some tags html.
@Johnrobmiller thanks for providing this workaround.
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.
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;
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);
}}
/>
@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;