I have been implementing Tyler McGinnis curriculum to learn react.
It's a weather app. And i'm having trouble debugging a strange behaviour. I'm pretty sure it's something silly that i'm doing or i might have missed an information piece of information.
SearchContainer
is a ParentContainer,
var React = require("react");
var Search = require("../components/Search");
var SearchContainer = React.createClass({
propTypes: {
formType: React.PropTypes.string
},
contextTypes: {
router: React.PropTypes.object.isRequired
},
getDefaultProps: function() {
return {
formType: "form"
}
},
getInitialState: function() {
return {
city: ""
}
},
handleSearchSubmit: function(e) {
e.preventDefault();
this.context.router.push('/forecast/' + this.state.city);
},
handleCityChange: function(e) {
this.setState({
city: e.target.value
});
},
render() {
return (
<Search
formType={this.props.formType}
city={this.state.city}
onCityChange={this.handleCityChange}
onSearchSubmit={this.handleSearchSubmit}/>
);
}
})
module.exports = SearchContainer;
SearchContainer
changes Context and switches to ForecastContainer
,
var React = require("react");
var Forecast = require("../components/Forecast");
var Api = require("../helpers/Api");
var ForecastContainer = React.createClass({
getInitialState: function() {
return {
isLoading: true,
data: []
}
},
makeRequest: function(city) {
this.setState({
isLoading: true,
});
Api.getDayForecast(city).then( function(data) {
this.setState({
isLoading: false,
data: data.data.list
});
}.bind(this) );
},
componentDidMount: function() {
this.makeRequest(this.props.params.city);
},
componentWillReceiveProps: function(newProps) {
this.makeRequest(newProps.params.city);
},
render() {
return (
<Forecast isLoading={this.state.isLoading} data={this.state.data} />
)
}
});
module.exports = ForecastContainer;
Now here, componentWillReceiveProps
is called twice. I don't understand why. Technically it should be just called once. I'm updating state in MakeRequest
method. It's called second time after state change.
I'm also enclosing screenshots for better understanding of Application flow.
Update:
I was using React-Router version 3.0.3. Downgrading to 2.0.0 fixes it. Which is all the more strange.
componentDidMount() may be called multiple times if the key prop value for the component changes.
Your component will get unmounted every time you change route, and a new one will be mounted when you change back.
The reason why this happens is an intentional feature of the React. StrictMode . It only happens in development mode and should help to find accidental side effects in the render phase.
I can't tell you why it is called twice, but I can tell you that it should not matter. The problem is that you're not comparing the props for what has changed. If you do this, the code will behave the way you want:
componentWillReceiveProps: function(newProps) {
if (newProps.params.city !== this.props.params.city) {
this.makeRequest(newProps.params.city);
}
},
See also the official ReactJS documentation, which states (emphasis mine): https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops
Note that React may call this method even if the props have not changed, so make sure to compare the current and next values if you only want to handle changes. This may occur when the parent component causes your component to re-render.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With