Handling both clicks and keypresses in React number input not working

Viewed 154

I have part of some React code below, where I have a number input, I'd like to prevent people being able to click below 0, which I've done with the min attribute. However I've seen that it's possible to still manually key in negative numbers. After some googling I've seen that people can handle this with a keyPress check and looking at the character codes but for some reason I can't quite get this to work.

Are both handlers clashing with each other? My goal is to allow click increments to work for positive numbers and prevent negative and decimal numbers being allowed in the input.

It's a controlled input, where value is coming from state.

const handleChange = (e) => {
    console.log(e.target.value);
    setCount(e.target.value);
  };

  const handleKeyPress = (e) => {
    console.log(e.target.value);
    console.log(e.charCode);
    if (e.charCode >= 48 && e.charCode <= 57) {
      setCount(e.target.value);
    }
  };

  return (
    <section>
      <h3>Input test</h3>
      <form onSubmit={handleSubmit}>
        <label htmlFor="amount">paragraphs:</label>
        <input
          type="number"
          name="amount"
          id="amount"
          min="0"
          value={count}
          onKeyPress={handleKeyPress}
          onChange={handleChange}
        />
2 Answers

You can format your value to absolute integer in your handleChange function and it would remove the zero and decimal separator on re-render:

const handleChange = (e) => {
  setCount(Math.abs(parseInt(e.target.value)));
};

Or if you absolutely want to prevent "0" and "." characters to be entered, you can use preventDefault in your handleKeyPress function:

const handleKeyPress = (e) => {
  if (e.charCode === 45 || e.charCode === 46) {
    return e.preventDefault()
  }
};

In this case you would like to use onKeyPress as a validator only. If validation fails, you can call e.preventDefault(). This way it will prevent to trigger onChange:

  const handleKeyPress = (e) => {
    if (e.charCode >= 48 && e.charCode <= 57) return
    e.preventDefault()
  };
Related