admin管理员组

文章数量:1026144

I have a simple controlled input of type number like below.

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

My value often returns a decimal number like 123.123 . My problem is, when I try edit the value. The cursor loses focus and shifts to the beginning ignoring the whole numbers as soon as the decimal places are cleared. Like below:

How do I address this? Immediately after the decimal places are cleared, the cursor jumps to the beginning thereby making it impossible to edit the whole numbers. Any help would be appreciated.

Update Below is the remaining code as requested by the user below.

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

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

And my updateMyChange method is simply

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

It does nothing much simply sets the new value. The cursor position jumps to the end as soon as decimal places are cleared. It does not set cursor for whole numbers.

I have a simple controlled input of type number like below.

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

My value often returns a decimal number like 123.123 . My problem is, when I try edit the value. The cursor loses focus and shifts to the beginning ignoring the whole numbers as soon as the decimal places are cleared. Like below:

How do I address this? Immediately after the decimal places are cleared, the cursor jumps to the beginning thereby making it impossible to edit the whole numbers. Any help would be appreciated.

Update Below is the remaining code as requested by the user below.

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

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

And my updateMyChange method is simply

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

It does nothing much simply sets the new value. The cursor position jumps to the end as soon as decimal places are cleared. It does not set cursor for whole numbers.

Share Improve this question edited Jul 25, 2016 at 1:53 Ben Hare 4,4255 gold badges29 silver badges46 bronze badges asked Jul 22, 2016 at 3:14 Nuru SalihuNuru Salihu 4,98818 gold badges73 silver badges120 bronze badges 8
  • 1 Show more of your code, maybe the entire ponent – Nicola Pedretti Commented Jul 22, 2016 at 4:01
  • @NicolaPedretti pls see my update above. – Nuru Salihu Commented Jul 22, 2016 at 4:59
  • 1 sorry, i just focused on the cursor part since seemed your biggest concern. here is the updated example. jsfiddle/bsoku268 using refs is the remended way of accessing elements in react. – Dayan Moreno Leon Commented Jul 22, 2016 at 7:09
  • 2 @DayanMorenoLeon it still persists if you use type="number". This issue seems to be a bug in the react lib itself since there are several reported bugs pertaining similar issues because of out of order rendering/inconsistencies. – code-jaff Commented Jul 22, 2016 at 8:20
  • 1 This issue wasn't present on v15.0.1, so you have the option of downgrading React version just slightly. – Hugo Silva Commented Jul 25, 2016 at 23:17
 |  Show 3 more ments

1 Answer 1

Reset to default 4

This is how React updates an input field's value:

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

When you set value attribute using that method, the caret goes to the beginning of the field, regardless of using React. You can see what I am saying in this fiddle - https://jsfiddle/5v896g3q/ (Just try and position the cursor in the field, between changes).

According to MDN, setAttribute is unstable when dealing with value. The remended way of changing value is by accessing the value property of the element, like element.value = newValue. If you use that approach, all seems to go as expected.

This is all I can tell for sure. Now let's speculate a little. When you type anything in that field, you are:

  1. updating the value of the input
  2. reading that value, and sending to React as state
  3. React updates the value of the input, with the new state

When you are typing on the field, step 3 is likely to have no impact, because when the value es back, the input already got it right. Except on the case with the float number. When your field reads 1., the actual value React updates the field with is 1. And React uses the evil method (setAttribute).

So, a workaround I found was setting the value of the field, using the proper method, before React touches it, on ponentWillUpdate:

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

The problem there, is that it is "numerizing" the value on every change, meaning I won't be able to have a point (1.). For that reason, I will only edit the input in case new value is 2 characters shorter than the old one (point + digit after point):

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

Working example - https://jsfiddle/bsoku268/3/

note: the fiddle is for demonstration purposes, and not supposed to be a bulletproof solution, as there are many ways of interacting with an input field, such as copy & paste, drag & drop, autofill, etc

I have a simple controlled input of type number like below.

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

My value often returns a decimal number like 123.123 . My problem is, when I try edit the value. The cursor loses focus and shifts to the beginning ignoring the whole numbers as soon as the decimal places are cleared. Like below:

How do I address this? Immediately after the decimal places are cleared, the cursor jumps to the beginning thereby making it impossible to edit the whole numbers. Any help would be appreciated.

Update Below is the remaining code as requested by the user below.

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

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

And my updateMyChange method is simply

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

It does nothing much simply sets the new value. The cursor position jumps to the end as soon as decimal places are cleared. It does not set cursor for whole numbers.

I have a simple controlled input of type number like below.

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

My value often returns a decimal number like 123.123 . My problem is, when I try edit the value. The cursor loses focus and shifts to the beginning ignoring the whole numbers as soon as the decimal places are cleared. Like below:

How do I address this? Immediately after the decimal places are cleared, the cursor jumps to the beginning thereby making it impossible to edit the whole numbers. Any help would be appreciated.

Update Below is the remaining code as requested by the user below.

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

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

And my updateMyChange method is simply

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

It does nothing much simply sets the new value. The cursor position jumps to the end as soon as decimal places are cleared. It does not set cursor for whole numbers.

Share Improve this question edited Jul 25, 2016 at 1:53 Ben Hare 4,4255 gold badges29 silver badges46 bronze badges asked Jul 22, 2016 at 3:14 Nuru SalihuNuru Salihu 4,98818 gold badges73 silver badges120 bronze badges 8
  • 1 Show more of your code, maybe the entire ponent – Nicola Pedretti Commented Jul 22, 2016 at 4:01
  • @NicolaPedretti pls see my update above. – Nuru Salihu Commented Jul 22, 2016 at 4:59
  • 1 sorry, i just focused on the cursor part since seemed your biggest concern. here is the updated example. jsfiddle/bsoku268 using refs is the remended way of accessing elements in react. – Dayan Moreno Leon Commented Jul 22, 2016 at 7:09
  • 2 @DayanMorenoLeon it still persists if you use type="number". This issue seems to be a bug in the react lib itself since there are several reported bugs pertaining similar issues because of out of order rendering/inconsistencies. – code-jaff Commented Jul 22, 2016 at 8:20
  • 1 This issue wasn't present on v15.0.1, so you have the option of downgrading React version just slightly. – Hugo Silva Commented Jul 25, 2016 at 23:17
 |  Show 3 more ments

1 Answer 1

Reset to default 4

This is how React updates an input field's value:

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

When you set value attribute using that method, the caret goes to the beginning of the field, regardless of using React. You can see what I am saying in this fiddle - https://jsfiddle/5v896g3q/ (Just try and position the cursor in the field, between changes).

According to MDN, setAttribute is unstable when dealing with value. The remended way of changing value is by accessing the value property of the element, like element.value = newValue. If you use that approach, all seems to go as expected.

This is all I can tell for sure. Now let's speculate a little. When you type anything in that field, you are:

  1. updating the value of the input
  2. reading that value, and sending to React as state
  3. React updates the value of the input, with the new state

When you are typing on the field, step 3 is likely to have no impact, because when the value es back, the input already got it right. Except on the case with the float number. When your field reads 1., the actual value React updates the field with is 1. And React uses the evil method (setAttribute).

So, a workaround I found was setting the value of the field, using the proper method, before React touches it, on ponentWillUpdate:

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

The problem there, is that it is "numerizing" the value on every change, meaning I won't be able to have a point (1.). For that reason, I will only edit the input in case new value is 2 characters shorter than the old one (point + digit after point):

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

Working example - https://jsfiddle/bsoku268/3/

note: the fiddle is for demonstration purposes, and not supposed to be a bulletproof solution, as there are many ways of interacting with an input field, such as copy & paste, drag & drop, autofill, etc

本文标签: javascriptReactjs controlled text cursor focus issueStack Overflow