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}
/>
);
}
- 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.
- 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}
/>
);
}