React: Input type="number" fields don't call onChange

Created on 23 Aug 2019  路  11Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?
bug
What is the current behavior?

<input type="number"> fields do not call onChange, and ignore their controlled value if text is entered into them. Upon a number being entered, they start to use onChange correctly.

What is the expected behavior?
In the following example, either the input should not allow non-numeric values at all OR it should call onChange on every value change. Instead, typing any alphabetic character is rendered in the input, but onChange is not called
https://codesandbox.io/s/serverless-morning-ct2ss

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
Unsure

Most helpful comment

I'm running into the same issue as well, with both examples.

I think the problem he's describing is that when you type in non-numeric characters in <input type="number"/>, the input field is rendering with the characters being typed in, but the onChange function is not being called. onChange seems to only get called if the user types in a number

In chrome, you can try typing characters like "e", "E", "-" etc. You can see the characters being added to the input, but onChange is not called. It seems in Firefox and Edge, the inputs are not restricted at all, so any characters will trigger this issue.

Chrome 76.0.3809.100 64bit
Firefox 68.0.2 64bit

All 11 comments

Hey @CluEleSsUK, thanks for filing this!

I had a question about your example:

function App(props) {
  return <input type="number" value={props.value} onChange={props.onChange} />;
}

const rootElement = document.getElementById("root");
var value = "";
const onChange = event => {
  console.log("onChange called");
  value = event.target.value;
};
ReactDOM.render(<App value={value} onChange={onChange} />, rootElement);

With this code, no state change occurs, so the controlled input does not receive a new value. React doesn't know to render again. What if instead, you did something like this:

function App() {
  const [value, setValue] = useState("");

  const onChange = event => {
    console.log("onChange called");
    setValue(event.target.value);
  };

  return <input type="number" value={value} onChange={onChange} />;
}

I made an example of that here:
https://codesandbox.io/s/new-darkness-wzgnt

If you follow this pattern, does the problem persist for you? If so, could you share what browser and browser version you are using?

I'm running into the same issue as well, with both examples.

I think the problem he's describing is that when you type in non-numeric characters in <input type="number"/>, the input field is rendering with the characters being typed in, but the onChange function is not being called. onChange seems to only get called if the user types in a number

In chrome, you can try typing characters like "e", "E", "-" etc. You can see the characters being added to the input, but onChange is not called. It seems in Firefox and Edge, the inputs are not restricted at all, so any characters will trigger this issue.

Chrome 76.0.3809.100 64bit
Firefox 68.0.2 64bit

Now that I look at it again, it looks like input.value (from the dom node) will be an empty string if the value in the input isn't a valid number. Since typing in just "e" is invalid, input.value doesn't change hence why onChange is not triggered. I'm guessing this is intentional

Oops yes my example was a little buggy; I still get the same behaviour on your example however. I am using Firefox developer edition 69.0b16

Ah right. If I remember correctly, Chrome does not emit change events for invalid values. Characters like e and - are valid text entry for number inputs because they are associated with scientific notation and negative numbers.

I believe we've hit this in the past, and there isn't anything we can do. For complete and utter control of the text, using an input with a type of text yields the best results.

Still, I can check to make sure this is consistent with what we've hit in the past before closing this issue.

I have resorted to using a text field indeed, which was a nice easy workaround; perhaps this could be reflected somewhere in the docs though, just to save others time and heartache 馃ぁ

@CluEleSsUK Usually reading the docs (not just React, but about HTML/JS too) helps to avoid such situations.

Thanks for your input @miraage

@CluEleSsUK AFAIK there are also some issues with number input on Android systems (not sure if they are still present, but definitely there were issues in the past). So it totally makes sense to be aware of different nuances in order to save nerves during development 馃檪

There doesn鈥檛 seem to be much react can do here. I鈥檓 going to close this issue, but feel free to discuss

I solved this issue by type="tel"

Was this page helpful?
0 / 5 - 0 ratings