Reputation: 47
I'm getting a mis-ordered response in React's setState with a select drop down I'm using. It's giving me the value of the previously selected option. When I first select something it comes out as blank, but the second select will give me the one I chose before.
So, first pick: "Green" results to empty Second pick: "Red" will give me 'gre' as result
I know I'm missing something, perhaps I'm not binding it correctly?
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
typeValue: ''
}
this.changeHandler = this.changeHandler;
this.expressValue = this.expressValue.bind(this);
}
expressValue(e) {
this.setState({
typeValue : e.target.value
});
console.log('this type val state is: ' + this.state.typeValue);
}
render() {
return (
<div>
<TypeSelect changeHandler={this.expressValue} />
</div>
)
}
};
class TypeSelect extends React.Component {
constructor(props) {
super(props);
}
render() {
let options = {
'default': 'Choose a category',
'red': 'Red',
'blu': 'Blue',
'gre': 'Green',
}
return (
<select name="name_type" id="name_type" onChange={this.props.changeHandler}>
{
Object.keys(options).map(function(key){
return (
<option key={key} value={key}>{options[key]}</option>
)
})
}
</select>
)
}
};
Upvotes: 1
Views: 2373
Reputation: 581
Roman's got it right, but I also wanted to point something else out:
this.changeHandler is not defined in your Main react component. And even if it was, you didn't bind it to (this).
In your constructor, change the line:
this.changeHandler = this.changeHandler;
to:
this.changeHandler = this.changeHandler.bind(this);
and then you would define a function by that name as you did expressValue().
Upvotes: 1
Reputation: 1635
this.setState()
changes the state asyncronously. It means, the value will be really changed with a bit delay. Usually it's not a problem, when you are relaying on state
after compomemnt update. But there you are trying to take a new value immediately. This won't work, as at this time you still don't have this value in the state
. In your particular case there are two ways.
First way. Use your origin value instead of state value in expressValue
function:
expressValue(e) {
this.setState({
typeValue : e.target.value
});
console.log('this type val state is: ' + e.target.value);
}
Second way. Show the message after the compoment was updated, for example, in render
method, wich is calling every time the state
was changes.
render() {
console.log('this type val state is: ' + this.state.typeValue );
return (
<div>
<TypeSelect changeHandler={this.expressValue} />
</div>
)
}
Upvotes: 1