Home > Net >  how to allow decimal value in TextField and keep state value also number in React
how to allow decimal value in TextField and keep state value also number in React

Time:01-18

I'm using React with Material UI and TypeScript. I want TextField to allow decimal value and at the same time keeping my state value as a number instead of string.

export default function BasicTextFields() {
  const [value, setValue] = React.useState(0);

  const handleChange = (event) => {
    const newValue = parseFloat(event.target.value);
    setValue(newValue);
  };

  React.useEffect(() => {
    console.log("value", typeof value);
  }, [value]);

  const handleKeyPress = (event) => {
    const pattern = /[0-9.]/;
    let inputChar = String.fromCharCode(event.charCode);
    if (!pattern.test(inputChar)) {
      event.preventDefault();
    }
  };

  return (
    <TextField
      value={value}
      onChange={handleChange}
      onKeyPress={handleKeyPress}
    />
  );
}
  1. I'm restricting the non numeric value with the use of handleKeyPress. Now I want my state value to remain number so I'm adding parseFloat, but parseFloat('5.') will resolve in 5 only so I'm not able to enter '.' in text-field at all.
  2. If I remove parseFloat it will allow decimal value but my state will be set as a string.

One possible solution is to use onBlur and setting up the state again with number value. To me this doesn't look the best way so any other way to solve this issue?

CodePudding user response:

Value from input field is always string so in my opinion you should just put type="number" in input, or pass it as props to TextField component, while leaving value state as string and convert it later in functions when needed.

I believe that would be best practice.

Or you can look at this code from youtuber web-dev-simplified: https://github.com/WebDevSimplified/react-calculator/blob/main/src/App.js He implements something similar.

CodePudding user response:

export const verify = (test: string) : boolean => {
var res: boolean = true;
let result: string = test.substr(0, test.length-1)
if (isNaN(test[test.length-1]) && test[test.length-1] !== "." ){
res = false;
}else{
if(isNaN(result)) {
res = false;
}}     
return res;
};   

then use this function before updating the useState Hook

 <TextField
  value={value}
  onChange={(event) => {
  if (verify(event.target.value)) {
  handleChange(event.target.value);
  }
  }}
  onKeyPress={handleKeyPress}
/>

CodePudding user response:

I would suggest to follow the next steps:

  • Remove onKeyPress event listener
  • Update your onChange event listener to store only float numbers in the state as string
  • Convert your string state to number by adding sign, if you want to use the float version of it in your code

Here's the updated version of your code:

export default function BasicTextFields() {
  const [val, setValue] = React.useState('');

  const handleChange = ({ target: { value } }) => {
    const onlyFloat = value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1');

    setValue(onlyFloat);
  };

  React.useEffect(() => {
    //will be string
    console.log("string version", typeof val);

    //will be float
    console.log("float version", typeof  val);
  }, [val]);

  // to use it as a float number just add the plus before val
  console.log( val);

  return (
    <TextField
      value={val}
      onChange={handleChange}
    />
  );
}
  • Related