React.js 与 'two children with the same key' 混淆

React.js confuse with 'two children with the same key'

我正在使用 React 在页面上安装两个相同的组件,

var SelectBox = React.createClass({
  getDefaultProps: function() {
    return {
      value: []
    };
  },
  getInitialState: function() {
    return {checked: this.props.value,count: 1};
  },
  handleClick: function() {
    var opt = this.state.checked;
    opt.push({id: this.state.count, name: this.state.count});
    this.setState({checked: opt, count: this.state.count + 1});
  },
  render: function() {
    var that = this;
    var options = this.state.checked.map(item => <option key={'checked-' + that.props.name + item.id} value={item.id}>{item.name}</option>);
    return (
      <div>
        <select multiple={true}>
          {options}
        </select>
        <button type="button" onClick={this.handleClick}>add</button>
      </div>
    );
  }
});
React.render(
  <SelectBox name='one'/>,
  document.getElementById('one')
);
React.render(
  <SelectBox name='two'/>,
  document.getElementById('two')
);

然后点击'one'的按钮,没问题,但是当我点击'two'的按钮时,一些'one'出现在'two',为什么??这让我很困惑。控制台显示:

Warning: flattenChildren(...): Encountered two children with the same key, `.$checked-two1`. Child keys must be unique; when two children share a key, only the first child will be used.

但只是做一些改变

var a = [{id: 5, name: 5}];
React.render(
  <SelectBox name='one' value={a}/>,
  document.getElementById('one')
);

它工作正常。 发生什么事了?有什么问题还是bug?

不,这里没有错误,您渲染了组件的同一个实例两次,这意味着 'components' 共享相同的状态,但是当您传递不同的道具时,组件现在有两个状态跟踪。

哦,我找到了真正的原因,getDefaultProps被调用一次并缓存,getDefaultProps()返回的任何复杂对象将跨实例共享,而不是复制,所以所有SelectBox组件没有传递的显式值属性将在状态中共享相同的已检查数组引用。 在这种情况下,我应该写:

  getInitialState: function() {
    var tmp = this.props.value.concat();
    return {checked: tmp, count: 1};
  },

当我在列表样式的反应组件中设置键时,我似乎遇到了这个问题,并且传递给键的 ID 不是唯一的,正如错误描述所暗示的那样。

例如 2 个列表项的键为 1。

这通常是因为设置您的唯一 ID 的逻辑错误。

在我的示例中,我为应用程序状态使用了 redux 存储,并且我将项目的 ID 设置为 items.length + 1,这是不正确的。

这导致了我上面的two children with the same key error。为了修复它,我将每个新项目的 id 设置为 itemsAdded 随着时间推移到列表的数量。

它类似于数据库中的键,其中 id 不断递增,因此由于将它们全部删除,您可能在数据库中没有任何项目,但是下一个项目的 id 可能是 1000。