React setState 在第一次尝试时不起作用,但在第二次尝试时起作用?

Posted

技术标签:

【中文标题】React setState 在第一次尝试时不起作用,但在第二次尝试时起作用?【英文标题】:React setState not working on first try, but works on second? 【发布时间】:2016-10-17 06:04:11 【问题描述】:

我在单击按钮时调用了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 函数之外的所有东西第一次都能正确执行?为什么它在第二次点击时起作用?

【问题讨论】:

您的if (this.state.foods[selectedFood]) 是否因某种原因无效?也许this.state.foods 第一次还是空的还是类似的? 您的getInitialState 函数中有什么?你可以发布整个组件,也许在 JSFiddle 中? 谢谢,我把所有东西都加到了 render 方法中 我可以通过替换它来让它工作:var state = Object.assign(this.state, selectedFoods: newSelections); this.setState(state); 这能回答你的问题吗? setState doesn't update the state immediately 【参考方案1】:

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

来自docs:

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

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

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

【讨论】:

这真是太好了。我的组件状态也没有得到更新,因为 DOM 没有按预期改变。 请注意:我正在为一个切换函数而苦苦挣扎,我需要这样的东西:“在 this.setState 之后我需要一个函数来触发。我通过在正如@Michael 所说,setState 回调,效果非常好。 谢谢!我有一段时间试图弄清楚这一点。现在我所有的 setState 都使用了回调,我没有任何问题。 优秀的答案。它帮助了我的代码;现在我可以在 setState 设置后立即提出请求。 :) 非常感谢。【参考方案2】:

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于React setState 在第一次尝试时不起作用,但在第二次尝试时起作用?的主要内容,如果未能解决你的问题,请参考以下文章

React.js setState 不起作用[重复]

ES6/React:为啥我的三重嵌套 setState 更新不起作用?

TypeError:未定义不是对象(评估'this.setState')[重复]

将元素推送到数组时反应setstate不起作用

React Switch Input 在第一次单击时未触发 SetState [重复]

在对数组进行排序并传递它之后,React 钩子 useState/setState 不起作用