React Native - 当数据没有改变时强制 ListView 重新渲染

IT技术 listview reactjs react-native
2021-05-11 06:15:27

是否可以强制 ListView 重新渲染,即使 dataSource 中的数据没有改变?我的应用程序的选项卡栏中有一个 ListView,我希望它在每次选择该选项卡时重绘,无论数据是否相同或已更改。

this.state = {
  data: props.data,
  dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
}

componentWillMount() {
  this.setState({
    dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
  })
}

render() {
  <ListView
   dataSource={this.state.data}
   renderRow={this._renderRow}
  />
}

我试着玩弄这些rowHasChanged论点,但这没有帮助。任何帮助将非常感激

4个回答

因此,据我所知,您的用例是由于value更改而重新呈现 ListView 的所有行我不知道是什么value,由你来决定,但我会用它value来解释我的答案:

有几种方法可以解决这个问题。各有利弊:

  • 简单的方法:只是<ListView key={value} ... />!!它告诉 React 当值改变时 ListView 需要重新渲染(它将被卸载,重新安装)。
  • “黑客方式”。替换为新的数据源。 this.setState({ dataSource: new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }).cloneWithData(this.props.data) });
  • (imo) 最佳实践方式:在数据中,value正确合并和实现 rowHasChanged。例如:(r1, r2) => r1.value !== r2.value && r1.data !== r2.data(<- 这只是表示数据的一种可能方式,您必须选择您的格式,我只是假设您使用 克隆了数据源nextProps.data.map(data => ({ data, value }))。

对我来说,第三个也是最后一个解决方案是最好的,因为:

  • 它可以很好地扩展到更多的重新渲染条件(其他value
  • 可能只有部分行实际上应该重新呈现,在这种情况下,您不应该重新呈现所有行以获得更好的性能。

这是我就该主题给出的另一个答案:

ListView.DataSource 中 rowHasChanged 的​​确切输入是什么

使用不变性方法

“更新”的最佳方法是克隆有问题的数据项,而不是像r1 !== r2已经暗示的那样进行标记黑客攻击不是更新单个项目,而是通过克隆更改“指针”本身。

对于这个特定问题,像这样更新数组中的项目。

arr[i] = { ...arr[i], someKey: newValue }

这将用“newValue”替换“someKey”属性,当前行将有一个新指针。

这是一个很好的资源,可以了解现代 JavaScript 中的不变性,这些资源对原生使用做出react:https : //wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/

您可以调用 this.forceUpdate() 来强制重新渲染。

您可以在onClick附加到选项卡的简单处理程序中执行此操作。

更多信息在这里,官方文档

但是,如果有其他规则规定是否应该更新,您可以尝试用dataSource完全替换,使其具有新的参考。这也将使其更新。

类似的东西

this.setState({ data : newDataSource… });

这可能有点矫枉过正,但我​​只是替换 componentDidUpdate 上的数据源(也许这对性能不利?我不知道哈哈)

  componentWillMount() {
   this.ds = new ListView.DataSource({
     rowHasChanged: (r1, r2) => r1 !== r2,
    });
   this.dataSource = this.ds.cloneWithRows(this.props.shiftsList);
  }

componentDidUpdate() {
  this.ds = new ListView.DataSource({
   rowHasChanged: (r1, r2) => r1 !== r2,
  });
 this.dataSource = this.ds.cloneWithRows(this.props.shiftsList);
}