Search code examples
listviewreact-nativereact-native-listview

Deleting a ListView item in React Native


I am having difficulty removing a row from a ListView. It removes the last element of the list, no matter which on is clicked. However, console.log tells me that the array has correctly deleted the item, but it renders wrongly... There are a few solutions already on the internet, but none have helped me solve my problem.

GIF of my problem

Logs

As you can see, it actually does remove the right item, but displays the wrong array?

Nov 6 22:18:39 Viviennes-Air reminders[25992] <Notice>: { rowID: '0' } Nov 6 22:18:39 Viviennes-Air reminders[25992] <Notice>: [ 'testing 2', 'testing 3' ] Nov 6 22:18:39 Viviennes-Air reminders[25992] <Notice>: { _rowHasChanged: [Function: rowHasChanged], _getRowData: [Function: defaultGetRowData], _sectionHeaderHasChanged: [Function], _getSectionHeaderData: [Function: defaultGetSectionHeaderData], _dataBlob: { s1: [ 'testing 2', 'testing 3' ] }, _dirtyRows: [ [ false, false, true ] ], _dirtySections: [ false ], _cachedRowCount: 3, rowIdentities: [ [ '0', '1', '2' ] ], sectionIdentities: [ 's1' ] }

Here's my constructor:

constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
  items: [],
  dataSource: ds.cloneWithRows([]),
  newItem: "",
};}

The ListView:

<ListView
        style={styles.container}
        dataSource={this.state.dataSource}
        enableEmptySections={true}
        renderRow={(data, sectionID, rowID) => this.renderRow(data, sectionID, rowID)}
        renderSeparator={(sectionId, rowId) => <View key={rowId} style={styles.separator}/>}
      />

The renderRow function:

renderRow(data, sectionID, rowID){
console.log("ITEM: ", data)
return <TouchableOpacity style={styles.listItem} onPress={() => this._delete({rowID})}
            activeOpacity={0.1}>
            <Text style={styles.listItemText}>{data}</Text>
            </TouchableOpacity>}

And finally, the delete function:

_delete(index){
  this.state.items.splice(index, 1)
  console.log(index)
  console.log(this.state.items)
  this.setState({
    dataSource: this.state.dataSource.cloneWithRows(this.state.items)
  })
  console.log(this.state.dataSource)}

I have been trying to figure this our for 2 hours now, and I'm pretty sure I'm doing everything correctly.


Solution

  • I agree with Burak Karasoy, But there is another mistake in the code.

    var newList= this.state.items.splice(index, 1)
    

    newList will contain the deleted item, but actually what we need is new List after deleting the item.

    So changes required to make your code work is,

    Do not store items in state object. Instead store it as class instance variable and set the dataSource, like below code

    this.items=this.getItems();
    this.setState({
            dataSource: this.state.dataSource.cloneWithRows(this.items)
     });
    

    Now update your _delete method like below

    _delete(index) {
        this.items.splice(index, 1)// This will remove the element at index, and update this.items with new array
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(this.items)
        });
    }