Reputation: 2577
I have a textarea where users input a location. Then, onBlur, the value of the weather is set and the result is supposed to change based on whatever the users typed in. The code works as it should. However, only if users fire it twice.
var Duck = React.createClass({
getInitialState:function() {
return {
deesfault: 'Houston, Texas',
setting: true,
main: '',
}
},
componentDidMount:function() {
return this.callthebase();
},
callthebase: function() {
var selfish = this;
$.get('http://api.openweathermap.org/data/2.5/weather?q='+this.state.deesfault+"&units=imperial&appid=~~appid~~", function(data){
selfish.setState(data);
});
},
changeit: function() {
this.setState({setting: false});
},
setsetting: function() {
this.callthebase();
this.setState({deesfault: document.getElementById('section').value});
this.setState({setting: true});
},
changesection: function() {
if (this.state.setting) {
return (<p onClick={this.changeit}>In {this.state.deesfault}</p>)}
else { return (<textarea id="section" defaultValue={this.state.deesfault} onBlur={this.setsetting} />) }
},
render: function() {
return (
<div>
{this.changesection()}
<p>The weather is {this.state.main.temp}</p>
</div>
)
}
});
As is, I would have to type in a location, blur out of it, and then come back in, activate it, and then blur it out again for the code to actually do what I want. This does not appear to be a problem when I use plain dummy text. But when I make an API call, this problem arises.
Upvotes: 0
Views: 157
Reputation: 1895
the below changes should work
componentDidMount:function() {
let data = this.callthebase(this.state.deesfault);
this.setState(data)},
callthebase: function(newValue){
return $.get('http://api.openweathermap.org/data/2.5/weather? q='+newValue+"&units=imperial&appid=~~appid~~", (data) => data);},
setsetting: function(){
let oldValue = document.getElementById('section').value;
let newValue = this.callthebase(oldValue);
this.setState({deesfault: newValue, setting: true});
},
Upvotes: 1
Reputation: 5166
You are calling callthebase, then setting deesfault to the new value.
setsetting: function(){
this.callthebase();
this.setState({deesfault: document.getElementById('section').value});
this.setState({setting: true});
},
changing it before calling callthebase will not solve your problem though because setState is called asynchronously:
from the documentation:
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.
what you could do is something like this:
setsetting: function(){
var newValue = document.getElementById('section').value;
this.callthebase(newValue);
this.setState({deesfault: newValue, setting: true});
},
and of course modify callthebase to take in the new value.
P.S. avoid assigning this
to a variable to be able to use it inside a function, you can use arrow functions from ES6 instead :)
callthebase: function(newValue){
$.get('http://api.openweathermap.org/data/2.5/weather? q='+newValue+"&units=imperial&appid=~~appid~~", (data) => {
this.setState(data);
});
},
Upvotes: 2
Reputation: 1201
What about adding onChange
property for your textarea:
_onChange: function(event) {
var value = event.target.value;
// process value and update state here
},
<textarea id="section" defaultValue={this.state.deesfault} onChange={this._onChange} />
Upvotes: 1