生命周期componentWillReceiveProps被多次调用

时间:2017-04-10 06:15:56

标签: reactjs react-router

我一直在实施Tyler McGinnis curriculum来学习反应。

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

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

更新

我使用的是React-Router 3.0.3版。降级到2.0.0修复了它。哪个更奇怪。

1 个答案:

答案 0 :(得分:24)

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

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

  

请注意,即使道具没有,React也可以调用此方法   已更改,因此确保比较当前值和下一个值   只想处理变化。父组件可能会发生这种情况   导致组件重新渲染。