'How to stop Editor draftJS cursor jumping to beginning of text while typing in React Hooks?
I have the problem with the drafjs plugin which is Editor, thing is it jumps to the beginning of the text when I am typing in the Editor. I have found How to stop DraftJS cursor jumping to beginning of text? this solution, but it is a bit different what I have in my code and in addition I made the component with new feature of React Hooks. Please, could you help me with this issue.
import {
EditorState, ContentState, convertToRaw,
} from 'draft-js'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import draftToHtml from 'draftjs-to-html'
import htmlToDraft from 'html-to-draftjs'
export default ({ value, onChange }) => {
const [editorState, setEditorState] = useState(EditorState.createEmpty())
useEffect(() => {
setEditorState(
EditorState.push(
editorState,
ContentState.createFromBlockArray(
htmlToDraft(value || ''),
),
),
)
}, [value])
return (
<div className="rich-editor">
<Editor
editorState={editorState}
onEditorStateChange={onEditorStateChange}
toolbar={{
options: ['inline'],
inline: {
options: ['bold', 'italic', 'underline'],
},
}}
/>
</div>
)
function onEditorStateChange(es) {
setEditorState(es)
const html = draftToHtml(convertToRaw(es.getCurrentContent()))
if (value !== html) {
onChange({ target: { name: 'text', value: html } })
}
}
}
Solution 1:[1]
ok I kind of figure out myself. However, it is not the best solution. Basically, I am converting the updated text to Html type, then comparing the value with converted darft.js editorState. Shortly, here is my code, if it helps to anyone in the future
import React, { useEffect, useState } from 'react'
import {
EditorState, ContentState, convertToRaw,
} from 'draft-js'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import draftToHtml from 'draftjs-to-html'
import htmlToDraft from 'html-to-draftjs'
export default ({ value, onChange }) => {
const [editorState, setEditorState] = useState(EditorState.createEmpty())
useEffect(() => {
if (toHtml(editorState) === value) return //added
setEditorState(
EditorState.push(
editorState,
ContentState.createFromBlockArray(
htmlToDraft(value || ''),
),
),
)
}, [value])
return (
<div className="rich-editor">
<Editor
editorState={editorState}
onEditorStateChange={onEditorStateChange}
toolbar={{
options: ['inline'],
inline: {
options: ['bold', 'italic', 'underline'],
},
}}
/>
</div>
)
function onEditorStateChange(es) {
setEditorState(es)
const html = toHtml(es) //added
if (value !== html) {
onChange({ target: { name: 'text', value: html } })
}
}
function toHtml(es) {
return draftToHtml(convertToRaw(es.getCurrentContent())) // added
}
}
Solution 2:[2]
Another way is check if the value is empty
useEffect(() => {
if (value === '') {
onEditorStateChange(EditorState.createEmpty())
}
}, [value === ''])
This way, when the value is empty, the editorstatechange is assigned once again as empty.. subsequent times it should work fine as it was initialised to empty and onEditorStateChange will not be called again from useEffect as value is not empty
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Feruza |
Solution 2 | Shivanand T |