看一下下面的代码,是否有更好的方法来获取在反应状态内包含特定键/值对的项的计数?

一旦我要处理的列表变大,此方法似乎可能会导致瓶颈。

这是手头问题的简化示例:



class App extends React.Component {
  constructor() {
    super();

    this.state = {
      animals: [
        {type: 'cat'},
        {type: 'dog'},
        {type: 'cat'},
      ]
    };
  }

  render() {
    return(
      <div className="app">
        <Categories state={this.state} />
      </div>
    );
  }
}

class Categories extends React.Component {
  constructor() {
    super();

    this.countItems = this.countItems.bind(this);
  }

  countItems(type) {
    var count = 0;

    for(var i = 0; i < this.props.state.animals.length; i++) {
      if(this.props.state.animals[i].type === type) {
        count++;
      }
    }

    return count;
  }

  render() {
    return(
      <div className="categories">
        <div>Total animals: {this.props.state.animals.length}</div>
        <div>Cats: {this.countItems('cat')}</div>
        <div>Dogs: {this.countItems('dog')}</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="container"></div>

最佳答案

当您经常调用此方法时,按类型对数据(动物)建立索引并在进行更改时保持更新可能会很有用。

例如:

App构造函数中,您将创建另一个属性animalsPerType

  constructor() {
    super();

    this.state = {
      animals: [
        {type: 'cat'},
        {type: 'dog'},
        {type: 'cat'},
      ]
    };
    this.state.animalsPerType = this.state.animals.reduce(function(acc, animal) {
        return acc.set(animal.type, (acc.get(animal.type) || []).concat(animal));
    }, new Map());
  }


然后,您的countItems方法变得很简单:

  countItems(type) {
    return this.props.state.animalsPerType.get(type).length;
  }

09-07 03:34