Stop cursor jumping when formatting number in React

An easy solution for losing cursor/caret position in the React's <input /> field that's being formatted is to manage the position yourself:

    onChange(event) {

      const caret = event.target.selectionStart
      const element = event.target
      window.requestAnimationFrame(() => {
        element.selectionStart = caret
        element.selectionEnd = caret
      })

      // your code
    }

The reason your cursor position resets is because React does not know what kinds of changes you are performing (what if you are changing the text completely to something shorter or longer?) and you are now responsible for controlling the caret position.

Example: On one of my input textfields I auto-replace the three dots (...) with an ellipsis. The former is three-characters-long string, while the latter is just one. Although React would know what the end result would look like, it would not know where to put the cursor anymore as there no one definite logical answer.


onKeyUp(ev) {
  const cardNumber = "8318 3712 31"
  const selectionStart = ev.target.selectionStart; // save the cursor position before cursor jump
  this.setState({ cardNumber, }, () => {
    ev.target.setSelectionRange(selectionStart, selectionStart); // set the cursor position on setState callback handler
  });
}

Tags:

Reactjs