Как остановить редактор 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, поскольку значение не пустое.

Другие вопросы по тегам