Reputation: 974
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 } })
}
}
}
Upvotes: 3
Views: 3216
Reputation: 61
add detail from my code:
export default function App(props) {
const [state, setstate] = useState(EditorState.createEmpty());
function toHtml(es) {
return draftToHtml(convertToRaw(es.getCurrentContent())); // added
}
useEffect(() => {
// check if reference value is null or empty
// check if there is changes in content, prevent cursor keypress as input
if (!props.value || toHtml(state) === props.value) return;
setstate(
EditorState.push(
state,
ContentState.createFromBlockArray(htmlToDraft(props.value || ""))
)
);
}, [props.value]);
function handleChange(raw) {
// directly update local state
setstate(raw);
// check if there is changes in content, prevent cursor keypress as input
// parent state updated only when content changes (without cursor)
if (props.value !== toHtml(raw)) {
props.onChange(draftToHtml(convertToRaw(raw.getCurrentContent())));
}
}
return (
<Editor
editorState={state}
onEditorStateChange={handleChange}
placeholder={props.label}
toolbar={{
options: ["inline"],
inline: { options: ["bold", "italic", "underline"] },
}}
/>
);
}
keyword code code as this :
toHtml(state) === props.value
this code preventing local state changes / parent value (onChange) updated on cusor keypresed
Upvotes: 0
Reputation: 1283
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
Upvotes: 0
Reputation: 974
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
}
}
Upvotes: 3