我知道这已经被问过,例如参见here,here和here。React原生ListView:删除时删除了错误的行
但是,没有一个答案/评论是令人满意的。他们要么告诉你克隆没有解决问题的数据,要么在ListView上设置一个唯一的键来解决问题,但创建一个新的键。
当您在ListView上设置唯一键并在删除后更新它时,整个视图会再次呈现并滚动到顶部。滚动列表以删除项目的用户期望列表保持其位置。
这里是一个人为的例子,使用的是什么我将承担为克隆数据的正确方法:
var ListViewExample = React.createClass({
getInitialState() {
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => {
r1 !== r2
}});
var rows = ['row 1', 'row 2', 'row 3'];
return {
dataSource: ds.cloneWithRows(rows),
};
},
_deleteRow() {
var rows = ['row 1', 'row 3'];
this.setState({dataSource: this.state.dataSource.cloneWithRows(rows)})
},
renderRow(rowData, sectionID, rowID) {
return <TouchableOpacity onPress={this._deleteRow}
style={{height: 60, flex: 1, borderBottomWidth: 1}}>
<Text>{rowData}</Text>
</TouchableOpacity>
},
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
);
}
});
而且here你可以看到它的GIF在哪里不对劲获得连续的删除动作。另一种方法,设置ListView的key
属性会删除正确的行,但正如我所说的将导致列表滚动到顶部。
UPDATE
我已经接受了纳德的答案下面但这似乎并没有被正确的做法,因为它不会对数据源调用rowHasChanged
。它也不符合ListView文档。它没有解决我的问题,所以我会离开它标记为答案,但我有一种感觉,这是一种解决方法,而不是正确的解决方案
另一个更新
好吧,这是尴尬的,但我的rowHasChanged
功能是缺少return
声明。我想我的咖啡中含有过多的ES6糖。
所以最后,如果你搞砸了你的rowHasChanged
功能,this._ds
将工作出于某种原因。如果你以正确的方式开始,你应该使用类似于:
this.setState({
dataSource: this.state.dataSource.cloneWithRows(rows)
});
当更新你的dataSource
。
还请记住,您需要新的rows
datablob。用cloneWithRows(rows.push(newRow)
之类的东西来改变它将不起作用,而cloneWithRows(rows.concat([newRow])
将起作用。
如果帮助别人......我是......让我的列表的深拷贝克隆之前的关键所以之前cloneWithRows做new_rows = ...行] –