React Native ListView:删除时删除了错误的行

Eys*_*ysi 9 listview react-native

我知道之前有人问过,例如这里,这里这里.

但是,没有一个答案/评论是令人满意的.它们要么告诉您克隆无法解决问题的数据,要么在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}
      />
    );
  }

});
Run Code Online (Sandbox Code Playgroud)

在这里,你可以看到它的GIF在行动哪里错了行获得的去除.替代方案,设置keyListView 的支柱确实删除了正确的行,但正如我所说,将导致列表滚动到顶部.

UPDATE

我已经在下面接受了Nader的答案,但这似乎不是正确的方法,因为它没有调用rowHasChangeddataSource.它也不符合ListView文档.它确实解决了我的问题所以我会把它标记为答案,但我觉得这是一个解决方法,而不是正确的解决方案

另一个更新

好吧这很尴尬,但我的rowHasChanged功能却缺少return声明.我想我的咖啡中含有太多的ES6糖.

总而言之,如果你搞砸了你的rowHasChanged功能,this._ds将会出于某种原因.如果你做事,从你开始的正确方法应该使用如下:

this.setState({
  dataSource: this.state.dataSource.cloneWithRows(rows)
});
Run Code Online (Sandbox Code Playgroud)

更新你的时候dataSource.

还要记住,您需要一个新的rows数据库.用类似的东西cloneWithRows(rows.push(newRow)将它变换到不会起作用的意思cloneWithRows(rows.concat([newRow]).

Nad*_*bit 5

我认为问题在于您是基于以前的ListView.DataSource实例设置数据源.我给自己定了什么,我谈论的演示在这里,并把下面的例子中有这样做的另一种方式一起.

试着这样做:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ListView
} = React;

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => { r1 !== r2 }});

var SampleApp = React.createClass({

  getInitialState() {
    var rows = ['row 1', 'row 2', 'row 3'];
    return {
      dataSource: ds.cloneWithRows(rows),
    };
  },

  _deleteRow() {
    var rows = ['row 1', 'row 3'];
    this.setState({dataSource: ds.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}
      />
    );
  }

});
Run Code Online (Sandbox Code Playgroud)

https://rnplay.org/apps/YGBcIA

您还可以在renderRow中使用rowID来标识要删除的项目,然后在删除功能中重置dataSource的状态.

看看我在这里设置的例子.此外,代码如下:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ListView
} = React;

var rows = ['row 1', 'row 2', 'row 3'];
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => {
      r1 !== r2
    }});

var SampleApp = React.createClass({

  getInitialState() {

    return {
      dataSource: ds.cloneWithRows([]),
      rows: rows
    };
  },

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

  _deleteRow(rowID) {
    this.state.rows.splice(rowID, 1)
    this.setState({
      dataSource: ds.cloneWithRows( this.state.rows ),
    })
  },

  renderRow(rowData, sectionID, rowID) {
    return <TouchableOpacity onPress={ () => this._deleteRow(rowID) }
      style={{height: 60, flex: 1, borderBottomWidth: 1}}>
      <Text>{rowData}</Text> 
    </TouchableOpacity>
  },

  render() {
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
      />
    );
  }

});
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 28,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    fontSize: 19,
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2707 次

最近记录:

9 年,7 月 前