9

I am trying to make a simple blog using React-Quill text editor. I want to get the value of the ReactQuill Editor and preview it on a different route. I've been trying to achieve this since quite a while now and each time I face the same issue, the quill editor loses focus after every key press and throws a warning in the console saying addRange(): The given range isn't in document.

I've observed one thing. When I just pass in the props to < CreateBlog /> without applying the route, it works perfectly fine. But as soon as I apply the routes to < CreateBlog /> component so that I can take the value from the editor and preview it on a different route, I start facing this issue. I think that the react-router is probably responsible for such behavior but I'm unable to figure out the exact reason and its fix. Please help me. I've attached my code below for reference.

App.js:

class App extends Component {

  constructor(){
    super()

    this.state = {
      title: '',
      text: ''
    }

    this.handleBlogTextChange = this.handleBlogTextChange.bind(this)
    this.handleBlogTitleChange = this.handleBlogTitleChange.bind(this)
  }

  handleBlogTextChange(value){
    this.setState({
      text: value
    })
    console.log(this.state.text)
  }

  handleBlogTitleChange(value){
    this.setState({
      title: value
    })
    console.log(this.state.title)
  }

  render(){
    return (
      <BrowserRouter>
        <div class="App">
          <Switch>
            <Route path='/createBlog' component={() => <CreateBlog text={this.state.text} handleBlogChange={this.handleBlogTextChange} /> } />
            <Route exact path='/preview' component={() => <PreviewBlog title={this.state.title} text={this.state.text} />} />
            <Redirect to='/createBlog' />
          </Switch>
        </div>
      </BrowserRouter>
    );
  }
}

export default App;

CreateBlog.js:

export default class CreateBlog extends Component {

    render() {
        return (
            <>
                   ----------
                        <TextEditor text={this.props.text} handleBlogChange={this.props.handleBlogChange} />
                   ----------
            </>
        )
    }
}

TextEditor.js:

class TextEditor extends Component {

    componentDidMount(){
        const input = document.querySelector('input[data-link]')
        input.dataset.link = 'https://google.co.in'
    }

    modules={
        toolbar: [
            [{ 'header': '1'}, {'header': '2'}, { 'font': [] }],
            [{size: []}],
            ['bold', 'italic', 'underline', 'blockquote','code-block'],
            [{'list': 'ordered'}, {'list': 'bullet'}, 
             {'indent': '-1'}, {'indent': '+1'},{'align': []}],
            ['link', 'image', 'video'],
            ['clean']
          ],
    }
    
    render() {
        return (
            <div className="editor">
                <ReactQuill theme="snow" placeholder="Enter story..." modules={this.modules} value={this.props.text} onChange={this.props.handleBlogChange} />
            </div>
        );
    }
}
Amogh Dixit
  • 207
  • 1
  • 3
  • 10

5 Answers5

1

If someone is still searching for an answer, here is how I fixed it

I removed modules and format props and it worked

0

use literal object as modules props, it will trigger component rerender , use useMemo hook to memorize modules prop to fix it.

0

The below solution work for me. Also no need to remove modules and format.

Just replace the empty state value, which you are passing in the react quill editor with some dummy text

For e.g, based on the above question

replace this

this.state = {
      title: '',
      text: ''
    }

with this

this.state = {
      title: '',
      text: 'hey add some text here
    }
sidd 5312
  • 151
  • 2
  • 3
0

I was able to solve it by updating the value of value to editor.getContents() inside the onChange callback, which is called back with onChange(content, delta, source, editor), also as mentioned here, in the onChange section we need to use editor specifically to get the new delta not the delta itself, reason explicitly mentioned too.

thus interms of code, what ended up working was :

...
 editing (content, delta, source, editor) {
          const newDelta = editor.getContents ();

          this.setState({value : newDelta, newDelta});
      }

render () {
...
return (
...
<ReactQuill
  theme       = {this.state.theme}
  readOnly    = {readOnly}
  value       = {value}
  placeholder = {'Loading notes...'}
  onChange    = {(content, delta, source, editor) => {this.editing (content, delta, source, editor);}}
  />
...
);
}
BROGRAMMER_01
  • 19
  • 2
  • 6
0

If the same thing happens to someone, with the useMemo hook it worked for me

const [value, setValue] = useState("");
    
    const handleMemo = useMemo(
        (content, delta, source, editor) => setValue(content),
        [value]
    );