Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the correct way to remove an item from a ListView data source #881

Closed
darylrowland opened this issue Apr 16, 2015 · 6 comments
Closed
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@darylrowland
Copy link
Contributor

Not sure if this is the right place to ask, but couldn't find any mention of this in the docs...

I want to delete an item in a ListView. At the moment I'm refreshing the whole data source with the new list. Is there a better way of doing this? My issue is that once I refresh, the ListView loses its scroll position and jumps back to the top.

@ide
Copy link
Contributor

ide commented Apr 16, 2015

You should clone your original data source, this time with all of the original data minus the item you want to remove. Then pass that data source into ListView during the next render() pass. Look at the Movies example to learn more about dynamic Lists.

@eysi09
Copy link

eysi09 commented Feb 15, 2016

@ide this does not work. See contrived example below:

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}
      />
    );
  }

});

listview

As this oversized GIF shows, row 3 is removed from the screen whereas the datasource after deletion looks like ['row 1', 'row 3'].

If I set a key on the ListView and update that key after deletion it works except the whole list scrolls to the top as @darylrowland mentions. A user who scrolls down a list to delete an item expects the list to maintain it's position.

@eysi09
Copy link

eysi09 commented Feb 15, 2016

Ah, there is a solution!

Instead of doing something like this:

this.setState({dataSource: this.state.dataSource.cloneWithRows(rows)}),

one can define ListView.DataSource globally outside the ListView (or with this._ds = new ListView.DataSource when setting the initial state) and then update the whole thing with

this.setState({dataSource: ds.cloneWithRows(rows)})

or

this.setState({dataSource: this._ds.cloneWithRows(rows)})

depending on how ListView.DataSource was initialized. See this Stackoverflow answer.

@xuyannan
Copy link

Same problem.
My solution is setting key to every TouchableOpacity component in renderRow function ,so that the ListView would delete the item as you expect.

@eysi09
Copy link

eysi09 commented Apr 6, 2016

Regarding my comment above: My rowHasChanged was missing the return statement.

So in conclusion, if you screw up your rowHasChanged function, this._ds will help you out for some reason. If you do things the right way to begin with you should probably use something like this.setState({dataSource: this.state.dataSource.cloneWithRows(rows)}).

It also works without setting a key to every TouchableOpacity component as @xuyannan suggested but I guess one can never be too safe.

@rammi44
Copy link

rammi44 commented Jan 2, 2018

    this.state.todoItemArray.splice(key, 1);
    this.state.todoItemArray = this.state.todoItemArray;
    this.setState({ todoItemArray: this.state.todoItemArray });

I am using this, item is deleting from the state,todoItemArray but not updating in list view DataSoruce.. the object not reaching to the datasource and doesn't renderRow as expected..

@facebook facebook locked as resolved and limited conversation to collaborators May 31, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 22, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

7 participants