Проблема с контролем текстового курсора React.js

У меня есть простой управляемый ввод номера типа, как показано ниже.

<input type="number" value={+value} step={1} onChange={this.updateMyChange} />

My value часто возвращает десятичное число, например 123.123. Моя проблема заключается в том, когда я пытаюсь изменить значение. Курсор теряет фокус и переходит в начало, игнорируя все числа, как только очищаются десятичные разряды. Как ниже:

введите описание изображения здесь

Как мне адресовать это? Сразу после удаления десятичных знаков курсор перескакивает в начало, тем самым делая невозможным редактирование целых чисел. Любая помощь будет оценена.

Обновление Ниже приведен код, запрошенный пользователем ниже.

render() {
   const {value} = this.state;

   return (
      <input type="number" value={+value} step={1} onChange={this.updateMyChange} />
   )
}

И мой метод updateMyChange просто

updateMyChange(e) {
  this.setState({ value: e.target.value });
}

Он ничего не делает, просто устанавливает новое значение. Позиция курсора перескакивает до конца, как только десятичные разряды очищаются. Он не устанавливает курсор для целых чисел.

Ответ 1

Вот как React обновляет значение поля ввода:

node.setAttribute(attributeName, '' + value);

Когда вы устанавливаете атрибут value с помощью этого метода, каретка переходит в начало поля, независимо от использования React. Вы можете видеть, что я говорю в этой скрипке - https://jsfiddle.net/5v896g3q/ (Просто попробуйте поместить курсор в поле, между изменениями).

Согласно MDN, setAttribute нестабилен при работе с value. Рекомендуемым способом изменения value является доступ к свойству value элемента, например element.value = newValue. Если вы используете этот подход, все, похоже, идет так, как ожидалось.

Это все, что я могу сказать наверняка. Теперь позвольте немного размышлять. Когда вы вводите что-либо в этом поле, вы:

  • обновление значения ввода
  • чтение этого значения и отправка в React as state
  • React обновляет значение ввода, с новым состоянием

Когда вы вводите текст в поле, шаг 3, вероятно, не будет иметь никакого влияния, потому что когда значение вернется, вход уже получил это право. За исключением случая с поплавковым номером. Когда ваше поле читает 1., фактическое значение React обновляет поле с помощью 1. И React использует метод зла (setAttribute).

Итак, обходной путь, который я нашел, - это установить значение поля, используя правильный метод, прежде чем React коснется его, на componentWillUpdate:

componentWillUpdate(nProps, nState){
  this.refs.input.value = '0' + nState.value
}

Проблема там в том, что она "подсчитывает" значение при каждом изменении, то есть я не смогу иметь точку (1.). По этой причине я отредактирую вход только в том случае, если новое значение будет на 2 символа короче старого (точка + цифра после точки):

componentWillUpdate(nProps, nState){
  if(this.state.value.length - nState.value.length === 2){
    this.refs.input.value = '0' + nState.value
  }
}

Рабочий пример - https://jsfiddle.net/bsoku268/3/

Примечание: скрипка предназначена для демонстрационных целей и не должна быть пуленепробиваемым решением, так как существует много способов взаимодействия с полем ввода, например, копирование и вставка, перетаскивание, автозаполнение и т.д.