14

我在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功能之外的一切都在第一次正确执行?为什么它在第二次点击时起作用?

4

3 回答 3

44

状态正在按照它应该的方式发生变化。问题是,console.log在您调用后立即发出的语句setState是在设置新状态之前触发的。

文档

setState()不会立即变异this.state,而是创建一个挂起的状态转换。调用此方法后访问this.state可能会返回现有值。

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

this.setState({selectedFoods: newSelections}, () => {
    console.log(this.state.selectedFoods);
});
于 2016-06-15T23:56:55.017 回答
2

正如@Micheal 所说, setState 函数保持挂起状态,并且第一个 console.log 有效。任何想查看或试验这种情况的人,都可以看看我的代码和box.io 示例。在这里,在 YesNoComponentWithClass 中,第一次单击时 yes 按钮记录为空,而 no 按钮记录预期值。

于 2020-10-13T15:30:20.417 回答
0

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

于 2019-10-24T09:03:12.663 回答