2017-04-10 259 views
7

我一直在执行Tyler McGinnis curriculum学反应。生命周期componentWillReceiveProps被多次调用

这是一个天气应用程序。而且我在调试一个奇怪的行为时遇到了麻烦。我很确定这是一件愚蠢的事情,或者我可能错过了一条信息。

SearchContainer是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改变上下文并切换到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; 

现在这里,componentWillReceiveProps被调用了两次。我不明白为什么。从技术上讲,应该只是调用一次。我正在更新MakeRequest方法的状态。它在状态改变之后被称为第二次。

我还附上截图更好地了解应用流量。

enter image description here

更新:

我使用阵营,路由器版本3.0.3。降级到2.0.0可以修复它。这更奇怪。

+0

所以我只是将react-router版本降级到2.0.0,现在componentWillReceiveProps被调用一次。这很奇怪。这是否与新的React-Router有关? – kishanio

回答

10

我不能告诉你为什么它被调用两次,但我可以告诉你,它应该没有关系。问题是你没有比较改变的道具。如果你这样做,代码将表现你所希望的方式:

componentWillReceiveProps: function(newProps) { 
    if (newProps.params.city !== this.props.params.city) { 
    this.makeRequest(newProps.params.city); 
    } 
}, 

参见官方ReactJS文件,其中规定(重点煤矿): https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops

注意阵营可以调用这个方法即使道具没有 改变,所以要确保,如果你 只想处理的变化比较当前和未来值。当父组件 导致组件重新呈现时,可能会发生这种情况。

+0

哦,是的,这就是我的想法。我做了一个比较,并继续进行。我不知道为什么我对此非常挑剔。仅仅通过降级反应路由器版本,它的工作原理也很有趣。 – kishanio

+0

@kishanio我的猜测是,由于某种原因,新的路由器导致重新呈现在文档中提到的一个。然而,它是*允许的*行为,而不是一个错误,所以如果没有令人信服的理由,我会回到路由器v3.0.3。 – Lucero