React setState在第一次尝试时没有工作,但第二次工作?

时间:2016-06-15 22:42:04

标签: javascript reactjs setstate

单击按钮时调用handleSelection方法,但是,如果在到达this.setState({selectedFoods: newSelections});时状态未设置,则单击按钮。方法中的其他所有内容都正确执行(因为我的各种console.logs告诉我:))。再次单击该按钮时,方法中的所有内容将再次执行,setState将起作用。

var Flavor = React.createClass({
  getInitialState: function() {
    return { foods: {}, selectedFoods: [], affinities: [] };
  },
        componentDidMount: function() {
            $.ajax({
              url: this.props.url,
              dataType: 'json',
              cache: false,
              success: function(data) {
                this.setState({foods: data});
              }.bind(this),
              error: function(xhr, status, err) {
                console.error(this.props.url, status, err.toString());
              }.bind(this)
            });
          },
  componentDidUpdate: function () {
    $('#select-food').selectize({
      onChange: this.handleSelection
      }
    );
  },
  handleSelection: function (e) {
    if (e.target) {
      var selectedFood = e.target.id;
    } else {
      var selectedFood = e;
    }
    console.log(selectedFood);

    if (this.state.foods[selectedFood]) {
      var selections = this.state.selectedFoods;
      var newSelections = selections.concat(selectedFood);
      console.log("newSelections: "+newSelections)
      var state = Object.assign(this.state, {selectedFoods: newSelections});
      this.setState(state);
      console.log("state: "+this.state.selectedFoods)
      this.handleAffinities();
    } else {
      console.log("** "+selectedFood+" **");
    }

  },
  handleAffinities: function() {

    console.log("selectedFoods: "+this.state.selectedFoods.length)
    if (this.state.selectedFoods.length > 0) {
      var allAffinities = this.state.selectedFoods.map((food) => {
        return this.state.foods[food];
      });
      console.log(allAffinities.length);
      console.log(allAffinities);

      var commonAffinities = allAffinities[0];

      allAffinities.forEach((affinities) => {
        commonAffinities = commonAffinities.filter((n) => {
          return affinities.indexOf(n) != -1;
        });
      })

      this.setState({affinities: commonAffinities});
    } else {
      this.setState({ affinities: [] });
    }

  },
  handleRemove: function(food) {
    var selectedFoods = this.state.selectedFoods;
    var index = selectedFoods.indexOf(food);
    var updatedSelection = selectedFoods.splice(index, 1);
    this.setState({selectedFoods: selectedFoods});
    this.handleAffinities();
  },

除了setState函数之外,为什么第一次所有内容都能正确执行?为什么它在第二次点击时起作用?

3 个答案:

答案 0 :(得分:28)

状态正在改变它应该的方式。问题是,在调用console.log之后,您的setState语句会在设置新状态之前触发。

来自docs

  

setState()不会立即改变this.state,但会创建待处理状态转换。在调用此方法后访问this.state可能会返回现有值。

如果您想在状态转换完成后触发console.log语句,请将函数作为回调传递给setState()

this.setState({selectedFoods: newSelections}, () => {
    console.log(this.state.selectedFoods);
});

答案 1 :(得分:2)

正如@Micheal所述,setState函数保持待处理状态,并且第一个console.log起作用。任何想查看或尝试这种情况的人都可以看看我的codesandbox.io example。在此处,在YesNoComponentWithClass内,“是”按钮在第一次单击时记录为空,而没有按钮记录期望值。

答案 2 :(得分:0)

我也经历了一天这个问题,并找到了解决方案。 我刚刚在myCode中添加了componentDidUpdate()方法,现在一切正常。 有关生命周期的流程,请查看链接中给出的生命周期图像。