Reputation: 6253
I have a simple onChange which takes the user's input pareses it and sets the state to render. Here is the code.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {
random: {
foo: 0
}
}
}
onChange(e) {
let random = this.state.random;
random[e.target.name] = parseFloat(e.target.value);
this.setState({random});
}
render() {
return (
<div className="App">
<input onChange={this.onChange.bind(this)} type="text" name="foo" value={this.state.random.foo} />
</div>
);
}
}
export default App;
What I don't understand is where my decimal is going. I know there is no validation in place to stop the user from entering letters, but this is just a sample app to test this issue I ran into. When I enter a decimal point in does not get rendered. Where am I going wrong?
Upvotes: 12
Views: 5576
Reputation: 232
The onChange event happens anytime you hit a key, which causes the function to run and parseFloat takes away .
from your number, and that's why you end up having 12 instead of 1.2, so before using parseFloat you need to check whether the last character is .
and add it back afterwards.
Upvotes: 3
Reputation: 2534
As other have said, the problem is that the number type doesn't hold enough information about the state of the input, so when 1.
makes a round trip it loses the .
.
In other words, an input is a widget for editing a string, and your state doesn't contain enough information to recreate that string correctly, and instead the decimal point gets lost.
Thus, one solution is to store it as a string in your state, perhaps called inputValue
. Then, using unidirectional data flow, manage the translation between that string and the parts of code that think of it numerically very explicitly. Converting from a string to a number is dangerous -- not every string represents a number, so that part of the code needs to deal with validation (and not lose track of the text input). And converting from a number to a string is risky, as you've already observed, so it should only be done when there is a good reason (for instance, the server is pushing an event that the data changed somewhere else, swap it out).
Upvotes: 2
Reputation: 7199
The problem is that React's onChange
doesn't behave like the browser's onChange
It behaves like onInput
So it is getting called every time you type a value. This results in your parseFloat
actually parsing 1.
instead of 1.2
and the parsed value of 1.
is 1
Upvotes: 9
Reputation: 17061
Change your default state to foo: 1.11
- you will be able to edit this value (It isn't solution it is clue).
The problem here is parseFloat
which is trims dot from end of string when you typing new float value, and return for your string parseFloat('0.')
value 0
, hence you see your behavior...
Upvotes: 0