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

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

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 15 (3 by maintainers)

Most upvoted comments

I solved this issue by type=“tel”

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

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 🤡

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.

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?