1

The default state is a number, adding and subtracting from the default state works as expected. When the input value is changed by typing a number in the input field the state changes to a string. What's wrong here?

const [value, setValue] = useState(1);

 const handleChange = e => {
        setValue(e.target.value)
    }
    const handleAdd = () => {
        setValue(value+1)
    }
    const handleSubtract = () => {
        setValue(value-1)
    }
return (
<input type='number' value={value} onChange={handleChange} />
<button label='+' onClick={handleAdd} />
<button label='-' onClick={handleSubtract} />
)
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Philip B.
  • 15
  • 1
  • 6

2 Answers2

1

Based on this:

The purpose of the number type is that mobile browsers use this for showing the right keyboards and some browsers use this for validation purposes.

To fix this, there is some approaches. But I suggest to you to parseInt the value when onChange. So:

  const [value, setValue] = useState(1);

  const handleChange = (e) => {
    setValue(parseInt(e.target.value));
  };
  const handleAdd = () => {
    setValue((prev) => prev + 1);
  };
  const handleSubtract = () => {
    setValue((prev) => prev - 1);
  };

  return (
    <div>
      <input type="number" value={value} onChange={handleChange} />
      <button label="+" onClick={handleAdd} />
      <button label="-" onClick={handleSubtract} />
    </div>
  );

Danial
  • 1,603
  • 2
  • 15
  • 24
0

What's wrong here?

e.target.value is a string, even if you type a number, you will be given a string in your event

setValue(e.target.value)

Your state now has a string inside it

setValue((prev) => prev - 1);

Your add and subtract methods now are working with a string and a number, you are now victim of coercion https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/

'2' + 1 = 21, so after your state becomes a string, your code won't work as you intended

You need to use parseInt as written in another answer, or parse in any way you want, but always make sure your state has the type you intended

const handleChange = e => {
        setValue(Number(e.target.value) || 0)
    }

That is another way, note that when parsing a string that cannot become a number you get NaN, the above code will make it become 0 instead, but you can handle it your way

iunfixit
  • 953
  • 3
  • 15