Задать вопрос
Kentavr16
@Kentavr16
long cold winter

Почему курсор переходит в начало строки в моем компоненте?

Создал компонент для просмотра/изменения записи, который вместо инпута использует элементы с contentEditable.
Компонент

type NoteEditorProps = {
  activeNote: Note | null;
  dispatch: Dispatch<Action>;
};

const NoteEditor = (props: NoteEditorProps) => {
  const [noteState, setNoteState] = useState<Partial<Note>>();
  const formatedLocalDateTime = useDatetimeInputDateFormat();
//хелпер, переводит дату в формат приемлемый для инпута
  const dateInputValue = noteState?.expiredAt
    ? formatedLocalDateTime(noteState.expiredAt)
    : formatedLocalDateTime(new Date());

  useEffect(() => {
//устанавливаю начальное состояние компонента
    if (props.activeNote !== null) {
      setNoteState(props.activeNote);
    }
  }, [props.activeNote]);

//собственно комплексный обработчик ввода для трех инпутов
  function inputsHandler(
    e: ChangeEvent<HTMLHeadingElement | HTMLParagraphElement | HTMLInputElement>
  ) {
    if (e.target.id === "expiredAt" && "value" in e.target) {
      setNoteState({ ...noteState, [e.target.id]: new Date(e.target.value) });
    } else if ("innerText" in e.target) {
      setNoteState({ ...noteState, [e.target.id]: e.target.innerText });
    }
  }

//гуард для проверки что все поля на месте при сабмите 
  function isNoteComplete(obj: Partial<Note> | undefined): obj is Note {
    return (
      obj?.noteName !== undefined &&
      obj?.noteText !== undefined &&
      obj?.expiredAt !== undefined &&
      obj?.createdAt !== undefined
    );
  }

//сабмит
  function handleNoteUpdate() {
    if (isNoteComplete(noteState)) {
      props.dispatch({
        type: "updateNote",
        payload: { updatedNote: noteState },
      });
    }
  }

  if (props.activeNote === null) {
    return (
      <div className="h-1/2 flex items-center justify-center">
        <p>
        Выберите запись для просмотра/редактирования.
        </p>
      </div>
    );
  }
  return (
    <div className="h-1/2 flex flex-col border-b-2 border-black">
      <h2
        className="text-2xl text-center font-bold my-2"
        contentEditable
        suppressContentEditableWarning={true}
        id="noteName"
        onInput={inputsHandler}
      >
        {noteState?.noteName}
      </h2>
      <p
        className="pl-4 m-6"
        contentEditable
        suppressContentEditableWarning={true}
        id="noteText"
        onInput={inputsHandler}
      >
        {noteState?.noteText}
      </p>
      <p className="m-2">
        Запись создана -  {noteState?.createdAt?.toLocaleString()}.
      </p>
      <div className="m-2">
        <CustomInput
          id="expiredAt"
          label="Дата напоминания"
          type="datetime-local"
          value={dateInputValue}
          onChange={inputsHandler}
        />
      </div>
      <CustomButton
        className="bg-green-300 rounded disabled:bg-gray-700 disabled:text-white  p-4 m-4 mr-6 self-end"
        disabledMessage="Все поля должны быть заполнены"
        onClick={handleNoteUpdate}
      >
        Подтвердить изменения записи.
      </CustomButton>
    </div>
  );
};

export default NoteEditor;



Прошу прощения за "простыню", специально ничего не убирал.
Собственно проблема - при вводе данных в элемент с contentEditable курсор после каждого ввода данных перескакивает в начало строки. Проблема известная, вот к примеру та же история, хоть и 6-летней давности вопрос.
Насколько я понял, проблема в изменении стейта и ререндерах. Окей. Я решил вопрос использованием рефов вместо стейта(костыли, откровенно говоря). Еще нормально работает, если повесить обработчик на onBlur вместо onInput.
Вопрос вот в чем - почему тогда в этом примере не происходит перескакивания курсора?
Есть ли аксакалы которые сталкивались с чем-то подобным?
  • Вопрос задан
  • 152 просмотра
Подписаться 1 Простой Комментировать
Решения вопроса 1
Alexandroppolus
@Alexandroppolus
кодир
Зачем тебе эта содомия с contentEditable, если там по факту обычный текст без форматирования?? Сделай на православных инпутах, не морочь себе голову
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы