kyun
kyun

Reputation: 10264

keep a variable type when I get value from input onchange with React-hooks

const { useState } = React;

const App = () => {
  const [num, setNum] = useState(0);
  
  return (
    <input type="number" value={num} onChange={(e)=>setNum(parseInt(e.target.value))} />
  )
}

ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root" />

I want to keep num's type as Number, not String.

but, onChange=(e=>setNum(e.target.value)) makes num's type String

I tried to change like this onChange={e=>setNum(parseInt(e.target.value))}.

but, when I inputted white-space, It occurs error.

Warning: Received NaN for the value attribute. If this is expected, cast the value to a string.

What is the best way to keep num's type?

Upvotes: 2

Views: 7145

Answers (4)

Niresh
Niresh

Reputation: 77

Instead of using a parseInt() you can also use Number() where the blank whitespace will automatically be converted to 0.

In case you the input field to be empty you use the defaultValue instead of value like this

const { useState } = React;

const App = () => {
  const [num, setNum] = useState(0);
  //changes made below
  return (
    <input type="number" defaultValue={num} onChange={(e)=>setNum(Number(e.target.value))} />
  )
}

ReactDOM.render(<App />, document.getElementById('root'));

However in your case the default value is 0 because that's the initial value of num

You can change it to this const [num, setNum] = useState('');

Note : It will only work for all numbers including decimals

Upvotes: 0

Abhinav Sancheti
Abhinav Sancheti

Reputation: 21

I resolved this issue by checking the NaN value.

<input
  type="number"
  onChange={e => {
      Object.is(NaN, parseInt(e.target.value))
          ?setNum(e.target.value)
          :setNum(parseInt(e.target.value))
      }
  }
  value = {num}
/>

Upvotes: 0

Helena L. Vaquera
Helena L. Vaquera

Reputation: 11

I had the same issue, and I just bypassed it by having the value of the input be equal to either the state or an empty string. that way it won't affect the state of the value and it will just be an empty string.

<input
  type="number"
  onChange={e => setNum(parseInt(e.target.value))}
  value = {num || ""}
/>

with this, I also added validation to make sure num does not stay as a NAN for long.

Upvotes: 1

Vlatko Vlahek
Vlatko Vlahek

Reputation: 1899

The issue stems from the fact that parseInt can break.

In case you cannot successfully parseInt your "string" input value, you will get an error. You can add a fallback to current value or reset to 0, or avoid calling setNum in case your parseInt fails.

import React, { useState } from 'react';

const App: React.FC = () => {
  const [num, setNum] = useState(0);

  return (
    <input
      type="number"
      onChange={e => setNum(parseInt(e.target.value) || num)}
    />
  );
};

export default App;

Upvotes: 5

Related Questions