Как остановить редактор JJ курсор перескакивает к началу текста при вводе в React Hooks?
У меня есть проблема с плагином drafjs, который является редактором, он переходит к началу текста, когда я набираю текст в редакторе. Я нашел Как остановить курсор DraftJS, переходящий к началу текста? это решение, но оно немного отличается от того, что есть в моем коде, и, кроме того, я сделал компонент с новой функцией React Hooks. Пожалуйста, не могли бы вы помочь мне с этим вопросом.
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 } })
}
}
}
3 ответа
Хорошо , я вроде сам разбираюсь. Однако это не лучшее решение. По сути, я конвертирую обновленный текст в тип HTML, а затем сравниваю значение с преобразованным darft.js editorState. Короче, вот мой код, если он кому-нибудь поможет в будущем
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
}
}
добавить детали из моего кода:
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"] },
}}
/>
);
}
код ключевого слова как это:
toHtml(state) === props.value
этот код предотвращает изменения локального состояния/родительское значение (onChange) обновляется при нажатии клавиши cusor
Другой способ - проверить, пусто ли значение
useEffect(() => {
if (value === '') {
onEditorStateChange(EditorState.createEmpty())
}
}, [value === ''])
Таким образом, когда значение пусто, изменение состояния редактора снова назначается пустым. В последующие разы оно должно работать нормально, поскольку оно было инициализировано пустым, и onEditorStateChange не будет снова вызываться из useEffect, поскольку значение не пустое.