Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input type="number" fields don't call onChange #16554

Closed
CluEleSsUK opened this issue Aug 23, 2019 · 15 comments
Closed

Input type="number" fields don't call onChange #16554

CluEleSsUK opened this issue Aug 23, 2019 · 15 comments

Comments

@CluEleSsUK
Copy link

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

@nhunzaker
Copy link
Contributor

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?

@canytra
Copy link

canytra commented Aug 23, 2019

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

@canytra
Copy link

canytra commented Aug 24, 2019

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

@CluEleSsUK
Copy link
Author

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

@nhunzaker
Copy link
Contributor

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.

@CluEleSsUK
Copy link
Author

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 🤡

@miraage
Copy link

miraage commented Aug 26, 2019

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

@CluEleSsUK
Copy link
Author

Thanks for your input @miraage

@miraage
Copy link

miraage commented Aug 26, 2019

@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 🙂

@threepointone
Copy link
Contributor

There doesn’t seem to be much react can do here. I’m going to close this issue, but feel free to discuss

@hosseinmd
Copy link

I solved this issue by type="tel"

@softwarenacho
Copy link

I solved this issue by type="tel"

this should be in the documentation 😄 saved me after hours of tries

@aelmi03
Copy link

aelmi03 commented Jan 29, 2022

I solved this issue by type="tel"

Thanks for sharing the solution! Saved me a lot of frustration.

@shmup
Copy link

shmup commented Feb 14, 2023

Especially frustrating when wanting to type a float into an input without a leading zero: .15 versus 0.15, the latter firing onChange, the former does not

@kerematam
Copy link

I solved this issue by type="tel"

Warning for the ones who are about to implement this:
It is against a11y rules! Number input should be number input.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants