javascript React.js 与“具有相同密钥的两个孩子”混淆
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29382526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React.js confuse with 'two children with the same key'
提问by alchemist
I'm using react to mounting two same components on a page,
我正在使用 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')
);
then click the button of the 'one', it's alright, but when i click the button of the 'two', some of 'one' crop up in 'two',why?? it make me confuse. console show:
然后点击'一'的按钮,没关系,但是当我点击'二'的按钮时,一些'一'突然出现在'二'中,为什么?这让我很困惑。控制台显示:
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.
but just do some change
但只是做一些改变
var a = [{id: 5, name: 5}];
React.render(
<SelectBox name='one' value={a}/>,
document.getElementById('one')
);
it work properly. what happenned?is there something wrong or it's bug?
它工作正常。发生了什么?有什么问题还是错误?
回答by alchemist
Oh,I find the real reason,getDefaultProps
is called once and cached, the any complex objects returned by getDefaultProps()
will be shared across instances, not copied, so all SelectBox components without an explicit value prop passed will share the same checked array reference in state.
in the case, i should write:
哦,我找到了真正的原因,getDefaultProps
调用一次并缓存,返回的任何复杂对象getDefaultProps()
将在实例之间共享,而不是复制,因此所有没有传递显式值 prop 的 SelectBox 组件将在 state 中共享相同的检查数组引用。在这种情况下,我应该写:
getInitialState: function() {
var tmp = this.props.value.concat();
return {checked: tmp, count: 1};
},
回答by Henrik Andersson
No, there is no bug here, you are rendering the same instance of the component twice which means that the 'components' share the same state but when you pass along different props the component now gets two states to keep track of.
不,这里没有错误,您将组件的同一个实例渲染两次,这意味着“组件”共享相同的状态,但是当您传递不同的道具时,组件现在会获得两个状态来跟踪。
回答by svnm
This problem seems to come up for me when I set the keys in a list style react component, and the id's passed into the keys are not unique, as the error description suggests.
当我在列表样式的反应组件中设置键时,这个问题似乎出现在我身上,并且传递到键中的 id 不是唯一的,正如错误描述所暗示的那样。
e.g.2 of the list items have a key of 1.
例如,列表项中有 2 个的键为 1。
This is usually due to an error in the logic of setting up your unique id's.
这通常是由于设置唯一 ID 的逻辑错误所致。
For my example I was using a redux store for the applications state, and I was setting the id of the item to be items.length + 1
which was incorrect.
在我的示例中,我为应用程序状态使用了 redux 存储,并且我将项目的 id 设置items.length + 1
为不正确的。
This caused the two children with the same key error
above for me. To fix it, I set each new item's id to be the number of itemsAdded
to the list over time.
这two children with the same key error
对我造成了上述情况。为了解决这个问题,我将每个新项目的 id 设置为itemsAdded
随着时间的推移列表的数量。
It is similar to keys in a database where the id keeps incrementing, so you can have no items in the database due to deleting them all, however your id for the next item could be 1000.
它类似于数据库中的键,其中 id 不断增加,因此由于将它们全部删除,数据库中可能没有任何项目,但是下一个项目的 id 可能是 1000。