zenoamaro/react-quill

Custom Editing Area losing focus in React 16

ahutch1211 opened this issue ยท 60 comments

I have noticed an issue after upgrading to React 16. I have a React Quill component that is being managed by the parent.

class Editor extends Component {
  constructor(props) {
    super(props);

    this.handleOnChange = this.handleOnChange.bind(this);
    this.handleOnBlur = this.handleOnBlur.bind(this);
  }

  handleOnChange(html, delta, source) {
    const { onChange } = this.props;

    if (source === 'user') {
      onChange(html);
    }
  }

  handleOnBlur(range, source, quill) {
    const { onBlur } = this.props;
    
    if (source === 'user') {
      onBlur(quill.getHTML());
    }
  }

  render() {
    const { value } = this.props;
    
    return (
      <ReactQuill
        value={value}
        modules={modules}
        onChange={this.handleOnChange}
        onBlur={this.handleOnBlur}
        theme="snow">
        <Container />
       </ReactQuill>
    );
  }
}

class Parent extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
      value: '<h1>Testing Quill</h1><strong>Custom Editing Area</strong>'
    };
    
    this.handleOnChange = this.handleOnChange.bind(this);
    this.handleOnBlur = this.handleOnBlur.bind(this);
  }
  
  handleOnChange(value) {
    this.setState({ value });
  }
  
  handleOnBlur(value) {
    this.setState({ value });
  }
  
  render() {
    return (
      <Editor
	value={this.state.value}
	onChange={this.handleOnChange}
	onBlur={this.handleOnBlur}
      />
    );
  }
}

This code appears to be working in React 15. However, in React 16, it will lose focus and throw this console error after an onChange event; The given range isn't in document. I believe this is due to the selection not being updated correctly. If you take out the custom editing area, this code will work inside React 16.

I have attached an example in Codepen, in here you can set the dependencies for React 15 vs React 16 to notice the error.

In the meantime, we have removed the custom editing area and wrapped React Quill with a styled component and an '.ql-editor' selector to add a custom style to the editing area.

Thanks for your time!

I have this issue as well. Tried a lot of things before finding this. Removing Custom Editing Area stopped the error.
Weird thing: On Firefox 58 i got the same lose focus behaviour but without the console error.

Any news on that problem ? I have it too... I found that the key of the div is updated each time you submit a statechange

This may be due to a change in the lifecycle of React components in React 16. One of these?

  • When replacing <A /> with <B />, B.componentWillMount now always happens before A.componentWillUnmount. Previously, A.componentWillUnmount could fire first in some cases.
  • Previously, changing the ref to a component would always detach the ref before that component's render is called. Now, we change the ref later, when applying the changes to the DOM.
  • It is not safe to re-render into a container that was modified by something other than React. This worked previously in some cases but was never supported. We now emit a warning in this case. Instead you should clean up your component trees using ReactDOM.unmountComponentAtNode. See this example.
nucab commented

Try to set an id for parent and child.

static getDerivedStateFromProps(props, state) {
  if (props.id !== state.id) {
    return {
      id: props.id,
      editorHtml: props.defaultValue,
    };
  }
  return null;
}

Like this: https://codesandbox.io/s/k3jqjr78pr ?
The component still loses its focus after each key press.
Tested on Chrome and Firefox, both on last version, Ubuntu Linux

Bertg commented

+1 Interested to see this fixed

+1 Same Issue

Noticed that error occurs only in dev mode, after I build assets with webpack it doesn't reproduce anymore.

Hey guys, can I work in this issue?

Yes, please do! @erick2014

Is there already a solution for this? Or a viable workaround?

I have migrated from React 15 to React 16 this weekend.
A perfectly working Quill now is very buggy...

When I type in my input field, many times (it seems to be working when typing REALLY slow) the cursor jumps back to position 0 (the front).
And I seem to be getting an error on Chrome when that happens: 'Given range isn't in document'.
The error only shows up on Chrome, but the cursor-jumping appears on all major browsers.

I would prefer not rewriting any Quill implementation code, since it was working smooth as butter on React15 and I am hesitant to rewrite/refactor and introduce bugs in existing production code...

Edit: currently working around this issue by not using children components in the QuillEditor ReactQuill component.

+1 same issue.

huy guys, I'm checking this issue to see what's the problem

@alexkrolick is there any contribution guide to follow? I have no idea how to debug this

You can step through the editor in the example with Chrome devtools

ddzy commented

+1 same issue.

+2 same issue too

ddzy commented

After insert a picture, the following error occurs when I enter something elseโ†“โ†“โ†“
issue

@alexkrolick do you mean checking the demo in the repo?

Yes, clone locally and run the demo build in package.json, then you can debug a live editor

same issue

Same issue

same issue

Are there any known workarounds to this bug?

I ended up using draft js after a lot of research on this.

Same issue....

Quill is brought to it's knees when using: "div className="my-editing-area"

Warning: isMounted(...) is deprecated in plain JavaScript React classes. Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.
react.development.js:129
Warning: replaceState(...) is deprecated in plain JavaScript React classes. Refactor your code to use setState instead (see facebook/react#3236).
react.development.js:129
addRange(): The given range isn't in document. quill.js:3145

My experience with Quill - Problems + solutions:

My environemt: imagine a left panel with items from 1 to 10, and the main container with 6 properties to be filled in by User with React Quill text editor, so 60 properties in total.
Each item is clickable, so after clicking item1, the 6 text editors gets shown (either empty or with previously saved data), when clicking item2, next 6 text editors gets shown either empty or with previously saved data), and so on....

Problem 1:
Now, it was like, when I typed 1111 into the item1 text editor field and then navigated to item2, the value for the latter was still 1111 - so it was showing the value for the item that was firstly clicked. Whichever item was clicked next, got the same value (of item1).

Solution:
in the text-editor.tsx, so the place where we instatiante the ReactQuill, we were setting its value by defaultValue property, and not by value - which means, that this component
was not managed by React, which means, that it was not responding (refreshing) when the props or state was change. So I changed that to value, which cause the next problem.

Problem 2:
it was like, when I typed first character, the Quill was totally losing focus and throwing "addRange(): The given range isn't in document." error

Solution:
It turned out, that the Quill was not initialized with the proper value - so the empty Delta format. What we were using was {} but what is declared as empty Delta looks like this { ops: [] }
the code snippet:
if( !content || content.length === 0 || ( content.constructor === Object && Object.entries(content).length === 0 )) {
content = { ops: [] }
}

and that this content goes to ReactQuill value property, so ..., value={content} ...

Problem 3:
This was a tricky one, but we have those 6 text editors per tiem, right. It was working like the first was ok, the second losed focus and "addRange(): The given range isn't in document." error, the third ok, the forth lost focus "addRange(): The given range isn't in document." error, and so on.

Solution:
It turned out that we had two instances of the Quill defined, but that is due to the specification of our environment. We have a common repository with shared custom components, like this ReactQuill wrapper, and that the sub-repositories that uses this common one together with its own. Meaning, the first one was defined in the sub-repository's package.json and the second one was in this common ones package.json. I removed the one from sub-repository and left only the one defined in common, so de facto, the one that have this wrapper component.

Problem 4:
We started using Quill with the string data format, but at some point last year we decided to abandon this format, because it was causing some strange and hard to solve problems with formatting (e.g. it was adding extra lines when User navigate to a view with Quill, but did nothing, etc), so we decided to change it to Delta format - without those problems. We could do it back then because the Quill is supporting both the formats by default. We did not need any data migration, because it was just working, the problems started to occure when we ofc upgraded to React 16+. This means, that we had an "old" data of type string, and the "new" ones with delta format. Now, inside the onQuillChange in text-editor-wrapper component we have sth like this:

onQuillChange(textHTML: string, delta: Delta, source: string, editor: Quill){
        let content: any = editor.getContents();  <---- this returns Delta to Parent component and handles it there 
		this.props.onChange(textHTML, content)

which means, that on every change it gets the content (which is the Delta) and returns it in callback together with textHTML.
So it was like this: when the initial format was string, the OnChange changes that to Delta and returned to be saved as Delta - it turned out that Quill does not "like" this on-the-fly change and looses the connection to its instance, hence the focus got lost and "addRange(): The given range isn't in document." error

Solution:
What I did is that inside the parent component, so the one that executes the callback, I modified the handler function to look more-less like this:

	handleTextChange = (html: String, delta: Delta) => {      
		if(typeof this.state.xxxxxxx.myPropertyUsingQuill === "string") {
            this.xxxxxAttributeChanged(html, 'myPropertyUsingQuill');
        } else {
            this.xxxxxAttributeChanged(delta, 'myPropertyUsingQuill');
        };
	}

so whenever it starts working on a string data initially, it continues on a string, and when the initial value is Delta, it is working on Delta.

Problem 5:
So we have this modified handler. Now, what it turned out, is that when You started working on item1, which is the Delta format, it works fine, than You navigate to next item, item2, which has a string format of the value saved inside, boom, the focus is lost and "addRange(): The given range isn't in document." error - the focus was also lost the other way arround with data formats mentioned.

Solution:
So it turned out, that once the React Quill is mounted, it is still the same instance when navigating between different items. The values are just passed in inside the props. So in this case, it instatiated itself with Delta, but after clicking on item2, it did not reinstantiated itself with the string format (so still waiting to use Delta, but got string), hence the problem, focus lost, "addRange(): The given range isn't in document." error. I solved that by adding the key property inside the declaration, so sth like this:

<MyTextEditor id="xxxxx_myPropertyUsingQuill" 
                                key={xxxxx.uniqueId}

this key property makes the MyTextEditor reinstantiate itself whenever the key is different.

Problem 6:
It was actually a corner case, because what we've found is that, when the value provided to Quill is an empty string, it fails because it starts as a string, but than the logic inside text-editor-component transformes it to Delta format and uses it as a Delta, so there is a problem. The original was string, but returned was Delta, so the focus is lost, "addRange(): The given range isn't in document." error.

Soliution:
I extended the callback handler in the parent component to look like this:

	handleTextChange = (html: String, delta: Delta) => {
		if(typeof this.state.xxxxxxx.myPropertyUsingQuill === "string"  && (this.state.xxxxxxx.myPropertyUsingQuill as string).length > 0) {
            this.xxxxxAttributeChanged(html, 'myPropertyUsingQuill');
        } else {
            this.xxxxxAttributeChanged(delta, 'myPropertyUsingQuill');
        };	
    }

This means, that for initial values provided to Quill that are of type string, but have something inside, it will work in the string mode,
and for empty formats and Delta-type values provided to Quill, it will work in Delta mode.

Hope it will help some of You guys help Your issues.

@MateuszKrazek
Thank you very much for the in depth explanation of each of the problems you faced and the solution corresponding to each. I actually have a similar setup with a side panel of items and a main container for each with multiple quill fields for each item. It sounds like each one of you quill components is using a passed value (via props) to initially show previously saved data if there is any. How were you able to set up your component to allow for the changed values in the editor to be "lifted up" to the parent?

Like a lot of other people who are seeing the "addRange(): The given range isn't in document" error, every time I try to call a function passed through props in the onChange() function I am faced with the addRange() error. If the component is uncontrolled (values are stored and updated withing the state and do not come from props) things work fine. Just curious if you found a way around this.

Thanks!

@dharnen
If the component is uncontrolled (so You are setting up the value via defaultValue property instead of value) You will most likely get wrong data when navigating across different items from left panel - What I did, is I pass this onChange function as a callback via props, jut like this:

  <ReactQuill             
                        id={ this.props.id ? this.props.id : "" } 
                        theme={"snow"}
                        readOnly={this.props.readonly}
                        placeholder={this.props.placeholder}
                        defaultValue= { ops: [] }
                        value={content}
                        onChange={this.onQuillChange.bind(this)} //this is a text editor component built-in function to handle the event
                    />
 onQuillChange(textHTML: string, delta: Delta, source: string, editor: Quill){
        let content: any = editor.getContents();
        this.props.onChange(textHTML, content);  // this is the event handling function sent via props
                
    }

@MateuszKrazek
Ahhh okay! I had everything set up correctly except for providing a blank delta for the default value. That seems to be the key. Once the defaultValue={ ops: [] } is set I was able to use the component with the passed onChange function as a true controlled component.

Thank you for your response!

If anyone else is playing with this. I did run into the situation that is explained in the react-quill documentation https://github.com/zenoamaro/react-quill#using-deltas where if you try to update the passed variable used for the ReactQuill 'value' with the delta from the getContents() function it will loop infinitely and crash the page. For this reason I'm storing both the html and delta values in the parent component but only passing the html back into the ReactQuill. The main reason I'm storing the delta is that I have the ability to add mentions and based on their presence, or lack there of, need to trigger other things on the page. The delta object is easier to parse through than a string or html. =)

Built a QQ group (770265969), can come in to discuss quill
ๅปบไธ€ไธชQQ็พค๏ผˆ770265969๏ผ‰๏ผŒๅฏไปฅ่ฟ›ๆฅ่ฎจ่ฎบvue-quill-editor

I had the same issue using quill-mention, the editor was loosing the focus everytime a key was pressed. The issue was that I was recreating modules at each render. Caching it fixed the problem. More details here: slab/quill#1940 (comment)

@MateuszKrazek Thanks for the explanation! Still trying to understand your pseudo-code for handletextChange in the parent component. What exactly is myPropertyUsingQuill and this.xxxxxAttributeChanged?

I've got a small clean prototype in codesandbox which has the addRange error as well as most of your suggested fixes; except handleTextChange. Any help would be appreciated. :)

https://codesandbox.io/embed/53p6q1lp2p

@myron-scerri, on your Code Sandbox...if you remove the inner child, the problem abates:

<div className="text-editor">
        <ReactQuill
          id={this.props.id ? this.props.id : ""}
          value={this.props.value}
          defaultValue={defaultValue}
          onChange={this.onQuillChange}
          placeholder={this.props.placeholder}
        >
          <div id="targetContainer" className="targetcomponent" />
        </ReactQuill>
</div>

to

<div className="text-editor">
        <ReactQuill
          id={this.props.id ? this.props.id : ""}
          value={this.props.value}
          defaultValue={defaultValue}
          onChange={this.onQuillChange}
          placeholder={this.props.placeholder}
        />
</div>

I had, again, the same issue and this time, it was caused by changing the value in the handler (removing extra <p><br></p>). I solved it by creating a local state updated when value changed:

function MyEditor({ value, onChange }){
 const [state, setState] = useState({ value });

  useEffect(() => {
    if (state.value !== value) setState({ value });
  }, [value]);

  return (
     <Editor
        value={state.rawValue || state.value || ''}
        onChange={rawValue => {
          const cleanedValue = rawValue.replace(/<p><br><\/p>/g, '');
          setState({ rawValue, value: cleanedValue });
          onChange(cleanedValue);
        }}
    />
  );
}

I had, again, the same issue and this time, it was caused by changing the value in the handler (removing extra <p><br></p>). I solved it by creating a local state updated when value changed:

function MyEditor({ value, onChange }){
 const [state, setState] = useState({ value });

  useEffect(() => {
    if (state.value !== value) setState({ value });
  }, [value]);

  return (
     <Editor
        value={state.rawValue || state.value || ''}
        onChange={rawValue => {
          const cleanedValue = rawValue.replace(/<p><br><\/p>/g, '');
          setState({ rawValue, value: cleanedValue });
          onChange(cleanedValue);
        }}
    />
  );
}

In my project with your code, the issue persist mate.

@renaudtertrais in your example you're not using a custom editing area, try this example and you will see this bug it's still open...

function MyEditor({ value, onChange }){
 const [state, setState] = useState({ value });

  useEffect(() => {
    if (state.value !== value) setState({ value });
  }, [value]);

  return (
     <Editor
        value={state.rawValue || state.value || ''}
        onChange={rawValue => {
          const cleanedValue = rawValue.replace(/<p><br><\/p>/g, '');
          setState({ rawValue, value: cleanedValue });
          onChange(cleanedValue);
        }}
    >
          <div id="target"></div>
    </Editor>
  );
}

I had this issue and got it working by using defaultValue instead of value

const MyEditor = () => {
  const [editorContent, setEditorContent] = React.useState(``)

  return (
    <ReactQuill
      defaultValue={editorState}
      onChange={(value) => setEditorState(value)}
     />
  )
}

@robphoenix check out this post #309 (comment) and read the Problem #1.

@MateuszKrazek ok, sorry you still have issues, this is just what fixed it for me ๐Ÿคทโ€โ™€๏ธ

FWIW I encountered the same issue when I included Quill in a functional component, which was then being rendered as a child of another functional component. The issue seemed to be present when I used a combination of onChange = evt => {} and modules={whatever}

The "solution" (read: workaround) was to use a class component instead for the Quill editor.

Below is my new (working) Quill component:

import React, { Component } from "react";
import ReactQuill from "react-quill";
import 'react-quill/dist/quill.snow.css';

export default class MessageComposer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            text: null
        };
    }

    handleSubmit = () => {
        this.props.submissionHandler(this.state.text);
        this.setState({
            text: null
        })
    }

    handleChange = (content, delta, source, editor) => {
       this.setState({
           text: content
       })
    };

    render() {
        return (
            <ReactQuill
                theme="snow"
                modules={{
                    keyboard: {
                        bindings: {
                            enter: {
                                key: 13,
                                handler: this.handleSubmit
                            }
                        }
                    }
                }
                }
                value={this.state.text}
                onChange={this.handleChange}
            />
        );
    }
}

Hope it helps.

@robphoenix solution worked great.

Side note: if one is fetching their defaultValue asynchronously, make sure it's received and set before rendering the quill component โ€” and this works great!

Hello all!

Most of the issues in this thread, with related issues related to state changes and focus management, have been a core topic in the latest beta versions. The update detection and regeneration mechanisms have been reworked, and everything should now work properly when using value, modules, deltas, parent components.

I have updated the Codepen on the original post to the latest beta, and I don't seem to be getting any ill effects anymore: https://codepen.io/zenojevski/pen/LYpbyVP?editors=0010

Can you verify? npm install react-quill@beta should do the trick


Note: white-space issues when using strings are acknowledged, even though there is no solution yet. They might be improved by using the matchVisual clipboard setting, or deltas, as has been suggested at various points in the thread. It will be addressed in the short term, at the very least via an official recommendation.

@zenoamaro apparently matchVisual will be removed in Quill v2. We are on the stable version (1.3), but it's something to be aware of.

Prevent creating modules object each render.
I used useMemo hook and it solved the problem

It's seems that each re-render the modules object are recreating. To prevent this behaviour, i used useMemo.

const modules = React.useMemo(
   () => ({
     toolbar: { ... }
   }),
   [<any-value-to-compare-or-none>]
)

thanks @marinona / @murillo94! Works perfectly now :)

+1 ,the way of @marinona and @murillo94 works !! Thx, you save my day.

You must use @murillo94 and/or @timtamimi's solution to work, every function and object has to be memoized as a prop or it will clear the focus - so best to use a class

i've got similar issue when used react-quill.

warning addRange(): The given range isn't in document.
and quill field loose focus.

i used react functional component with:

// two states

const [formStatus, setFormStatus] = useState(false);
const [formSchema, setFormSchema] = useState({ ...postForm });

// standart form handlers

const cleanFormState = () => {...}
const formValidation = (schema) => {
  ...
 setFormStatus(valid);
}
const handleChange = (e) => {...}
const handleTouch = (e) => {...}
const handleBlur = (e) => {...}
const handleSubmit = (e) => {...}

and a form as a return

<div>
  <form>
     {/* that includes **several input fields** and **ReactQuill** component as a main content field. */}
  </form>
</div>

okay. now what was the problem?

The issue uccurs while handling change value event.

BEFORE FIX

const handleChange = (e) => {		
	let updatedSchema = {
		...
	};			
	
	formValidation(updatedSchema);
        setFormSchema(updatedSchema);
};

AFTER FIX

const handleChange = (e) => {		
	let updatedSchema = {
		...
	};
	**// !!! important to save changed schema state first**		
	setFormSchema(updatedSchema);
	formValidation(updatedSchema);
};

thx. and hope it helps someone.

@timtamimi converting to class component did not work

thanks @marinona and @murillo94 it worked, i made a simple mistake of removing bolded completely

const modules = React.useMemo(
() => ({
toolbar: { ... }
}),
[]
)

either useMemo neither useEffect worked for me on "react-quill": "^1.3.5", "react": "^16.13.1"

const modules = useMemo( () => ({ toolbar: [[{ header: [1, 2, false] }], ['bold', 'italic', 'underline']], }), [] );

return ( <ReactQuill modules={modules} theme="snow" value={value} onChange={value => setValue(value)}> <div style={{ height: 200 }} /> </ReactQuill> );

either useMemo neither useEffect worked for me on "react-quill": "^1.3.5", "react": "^16.13.1"

const modules = useMemo( () => ({ toolbar: [[{ header: [1, 2, false] }], ['bold', 'italic', 'underline']], }), [] );

return ( <ReactQuill modules={modules} theme="snow" value={value} onChange={value => setValue(value)}> <div style={{ height: 200 }} /> </ReactQuill> );

@Thyrannoizer are you defining "modules" inside the component's definition? It should be outside and it might be the problem.
It should be like this:

const modules = ....

const MyComponent = () => {
return( <ReactQuill modules = {modules} ......./>
}

Hope it helps!

I've been having the same problem as @Thyrannoizer , doesn't matter whether i define modules inside an useMemo or outside the component's definition, my custom editing area still loses focus after typying and on the console appears a warning message quill.js:3195 addRange(): The given range isn't in document., i'm using "react": "^16.13.1" and "react-quill": "^1.3.5".
Here's my code, my TextArea component is just a custom div styled component.

import React, { useEffect, useMemo, useState } from "react";
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'; 

import {TextArea} from '../shared/styles'

    const modules = {
    toolbar: [ ['bold', 'italic', 'underline']]
    }

const Editor = (props) =>{
    const [value, setValue] = useState('')
    const onChange = (e) =>{
        
        setValue(e)
    }

   return (
    <ReactQuill 
        modules={modules}
        theme='snow'
        onChange={onChange}
        value={value}
        
>
    <TextArea/>
</ReactQuill>
 

   )
}

I've been having the same problem as @Thyrannoizer , doesn't matter whether i define modules inside an useMemo or outside the component's definition, my custom editing area still loses focus after typying and on the console appears a warning message quill.js:3195 addRange(): The given range isn't in document., i'm using "react": "^16.13.1" and "react-quill": "^1.3.5".
Here's my code, my TextArea component is just a custom div styled component.

import React, { useEffect, useMemo, useState } from "react";
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'; 

import {TextArea} from '../shared/styles'

    const modules = {
    toolbar: [ ['bold', 'italic', 'underline']]
    }

const Editor = (props) =>{
    const [value, setValue] = useState('')
    const onChange = (e) =>{
        
        setValue(e)
    }

   return (
    <ReactQuill 
        modules={modules}
        theme='snow'
        onChange={onChange}
        value={value}
        
>
    <TextArea/>
</ReactQuill>
 

   )
}

@MiguelAlvarez129 I think your problem is because you are trying to use the Quill Editor as a controlled component.
In the documentation they explain how "value" and "onChange" work in the Quill component, i hope it helps: https://github.com/zenoamaro/react-quill#usage
I've tried your example and it works as a uncontrolled component (removing "value" and "onChange" props).

THIS SOLUTION WORKED FOR ME IN REACT FUNCTIONAL COMPONENT AS WELL !!

Don't use ReactQuill as a controlled component. That means, remove "value" prop from ReactQuill because you dont need to set the value in ReactQuill explicitly because it handles that on its own. You can keep "onChange" function to get the updated value on every change. Now, just have a variable(not a state variable) and set that variable on every change. Then access that very variable when you want to get the whole content.

let data = null; const onChange = (content, delta, source, editor) => { data = content; };

<ReactQuill theme="snow" modules={modules} onChange={onChange} formats={formats} placeholder="Enter your thoughts..." > <div className="my-editing-area" /> </ReactQuill>

Hope this works for you too. !!

THIS SOLUTION WORKED FOR ME IN REACT FUNCTIONAL COMPONENT AS WELL !!

Don't use ReactQuill as a controlled component. That means, remove "value" prop from ReactQuill because you dont need to set the value in ReactQuill explicitly because it handles that on its own. You can keep "onChange" function to get the updated value on every change. Now, just have a variable(not a state variable) and set that variable on every change. Then access that very variable when you want to get the whole content.

let data = null; const onChange = (content, delta, source, editor) => { data = content; };

<ReactQuill theme="snow" modules={modules} onChange={onChange} formats={formats} placeholder="Enter your thoughts..." > <div className="my-editing-area" /> </ReactQuill>

Hope this works for you too. !!

That will work for simple cases but sometimes a controlled component is desirable. Eg if you want to modify the value in another component eg a "clear value" button, or if you want to take in asynchronous updates from the backend.

I had the same issue using quill-mention, the editor was loosing the focus everytime a key was pressed. The issue was that I was recreating modules at each render. Caching it fixed the problem. More details here: quilljs/quill#1940 (comment)

When I created a keyboard binding to disable delete key(key code 46) I was also facing issue with focus. I fixed the issue by putting my bindings outside of component.

Before:
keyboard:{
bindings: {//binding here}
}

After:
const bindings = {//binding here}//outside component

keyboard:{
bindings: bindings
}

thanks @marinona and @murillo94 it worked, i made a simple mistake of removing bolded completely

const modules = React.useMemo( () => ({ toolbar: { ... } }), [****] )

Thank mate, that work well

@alexkrolick why has this issue been closed? I see a couple of workarounds but the bug is still there.
It would be nice to close it once the problem itself is solved by the lib ๐Ÿค”