【问题标题】:React increment state from component反应来自组件的增量状态
【发布时间】:2015-03-11 21:42:35
【问题描述】:

我正在尝试创建一个类似于此处的反应示例的过滤表:Thinking in React。我想添加的是在总项目集中显示多少项目的计数。我的想法是在顶级组件“资源”中保留状态变量“numShowing”。我还在这个组件中创建了一个函数来使用 setState() 增加“numShowing”。然后,我将该函数沿组件链传递,并在安装感兴趣的组件时调用它。这是一些伪代码(我已经删除了不必要的东西和对过滤组件的引用):

组件层次结构为:Resources -> ResourcesTable -> ResourcesTableEntry。

var Resources = React.createClass({
  getInitialState: function() {
    return {
      numShowing: 0
    };
  },
  incrementShowing: function() {
    console.log('increment from: ' + this.state.numShowing);
    this.setState({numShowing: this.state.numShowing + 1});
  },
  render: function() {
      <div>
        <ResourcesTable resources={this.state.resources} incrementShowing={this.incrementShowing} />
      </div>
    );
  }
});

var ResourcesTable = React.createClass({
  createEntry: function(resource) {
      if (/* filtered out */) {
        return;
      } else {
        return(<ResourcesTableEntry key={resource.id} resource={resource} incrementShowing={this.props.incrementShowing} />);
      }
  },
  render: function() {
    return (
      <table>
          <tbody>
            { this.props.resources.map(this.createEntry) }
          </tbody>
      </table>
    );
  }
});

var ResourcesTableEntry = React.createClass({
  componentDidMount: function() {
    this.props.incrementShowing();
  },
  render: function() {
    return (
      <tr>
        /* output props here */
      </tr>
    );
  }
});

我还尝试从 ResourcesTable.createEntry 函数递增。在这两种情况下,numShowing 只会设置为 1。我认为这是因为 setState 是异步的或非原子的,因此每次调用 incrementShowing() 时 numShowing 的当前状态为 0(控制台输出验证函数被调用的次数正确)。那么这样做的“正确”方法是什么?

【问题讨论】:

    标签: reactjs setstate


    【解决方案1】:

    这里的问题是您不想在渲染方法中更新状态,因为它是一种反模式。该问题可以通过将过滤移至拥有numShowing 的组件,即Resources 来解决。这将消除对ResourceTable 组件的需求。

    var Resources = React.createClass({
      render: function() {
        numShowing = 0;
        filteredResources = this.state.resources.map(function(resource){
          if (/* filtered out */) {
            return;
          }
          numShowing++; 
          return(<ResourcesTableEntry key={resource.id} resource={resource} />);
        }.bind(this));
        return(
          <div>
            <span> Number of results: {numShowing} </span>
            {filteredResources}
          </div>
        );
      }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      相关资源
      最近更新 更多