我在删除React数组中的有状态元素时遇到问题。在以下示例中,如果单击第二个元素('B')上的'切换',您将看到:
条目ID:0名称:A是活动切换删除
条目ID:1名称:B未激活切换删除
条目ID:2名称:C是活动切换删除
如果您现在点击第一个元素('A')上的'删除':
条目ID:0名称:B是活动切换删除
条目ID:1名称:C未激活切换删除
B已更改,但我想要做的就是删除A而不影响任何其他元素。我根据文档得到key
,并尝试使用带字符串前缀的密钥,但它没有帮助。
有没有办法在不将状态推到TestContainer
的情况下执行此操作? (在我的实际情况中,我有很多不同类型的状态的不同元素。)
<div id="test"></div>
<script type="text/jsx">
var TestLine = React.createClass({
getInitialState: function() {
return {active: true};
},
handleLineRemove: function(e) {
this.props.processLineRemove(this.props.id);
},
toggleActive: function(e) {
this.setState({active: !this.state.active};
},
render: function() {
return (
<p>
Entry id: {this.props.id} name: {this.props.name}
{this.state.active ? " Is Active " : " Is Not Active " }
<a onClick={this.toggleActive}>Toggle</a>
<a onClick={this.handleLineRemove}>Remove</a>
</p>
);
}
});
var TestContainer = React.createClass({
getInitialState: function() {
return {data: {lines: ['A','B','C']}};
},
processLineRemove: function(index) {
var new_lines = this.state.data.lines.slice(0);
new_lines.splice(index,1);
var newState = React.addons.update(this.state.data, {
lines: {$set: new_lines}
});
this.setState({data: newState});
},
render: function() {
var body =[];
for (var i = 0; i < this.state.data.lines.length; i++) {
body.push(<TestLine
key={i}
id={i}
name={this.state.data.lines[i]}
processLineRemove={this.processLineRemove} />)
}
return (
<div>{body}</div>
);
}
});
React.render(<TestContainer />, document.getElementById('test'));
</script>
答案 0 :(得分:1)
如果列表中包含任意删除/插入,则不能将索引用作键。在这种情况下,您可以使用实际值,因为它没有更改。
var body = this.state.data.map(function(x, i){
return <TestLine
key={x}
name={x}
processLineRemove={this.processLineRemove.bind(null, i)} />
}.bind(this));
在更复杂的情况下,您需要一个对象数组,并为每个对象分配一个唯一值的属性。假设状态为[makeItem('A'), makeItem('B'), ...]
:
function unique(){ return ++unique.i };
unique.i = 0;
function makeItem(text){ return {text: text, id: unique()}; };
var body = this.state.data.map(function(x, i){
return <TestLine
key={x.id}
name={x.text}
processLineRemove={this.processLineRemove.bind(null, i)} />
}.bind(this));
答案 1 :(得分:0)
如果您有一个项目列表,并且您知道将随机编辑项目,我将不会创建这样的键。我希望创建唯一的密钥,并在列表更改时使用其他密钥will not overlap
。像this这样的简单随机密钥生成器就足够了。
为什么?让我们来看看每一步。
首次渲染看起来像这样
条目ID:0名称:A是活动切换删除
条目ID:1名称:B未激活切换删除
条目ID:2名称:C是活动切换删除
第二个看起来像这样
条目ID:0名称:B未激活切换删除
条目ID:1名称:C是活动切换删除
现在是React的时间来拍摄这两个,并弄清楚发生了什么变化。它将比较组件和键。
它着眼于第一个元素并理解&#34;活跃&#34; flag根据键设置为true。因此它将应用于在第二个渲染中找到的键0。等等剩下的元素。
因此,如果您的密钥在更改时不重叠,则可以避免此问题。 这是AFAIK的唯一途径。希望这会有所帮助。
这是解释上述内容的DEMO。