React native 在React Native中,将数据源加载到listView的正确方法是什么 在React Native中将数据源加载到listview的正确方法是什么?

React native 在React Native中,将数据源加载到listView的正确方法是什么 在React Native中将数据源加载到listview的正确方法是什么?,react-native,React Native,目前,我正在像下面这样做。这是可行的,但在我所有的列表中采用这个概念之前,我想了解一些信息。这是一个好的方法吗?我的原始数据保存在一个不可变的.List中 对于不习惯Immutable.js的读者:使用普通数组的区别在于我们需要调用list.get(rowId),而不是简单地调用array[rowId]。我们还需要将索引列表转换为数组keySeq().toArray() 在constructur中,我使用一个数据源初始化this.state,我还使用一个单独的函数(cloneDataSource

目前,我正在像下面这样做。这是可行的,但在我所有的列表中采用这个概念之前,我想了解一些信息。这是一个好的方法吗?我的原始数据保存在一个不可变的.List中

对于不习惯Immutable.js的读者:使用普通数组的区别在于我们需要调用list.get(rowId),而不是简单地调用array[rowId]。我们还需要将索引列表转换为数组keySeq().toArray()

在constructur中,我使用一个数据源初始化this.state,我还使用一个单独的函数(cloneDataSource)在该数据源上执行数据的初始克隆:

用于克隆数据行的函数从构造函数和componentWillReceiveProps调用。此特定列表视图有两个硬编码部分:

cloneDataSource(dataSource) {
  return dataSource.cloneWithRowsAndSections(
    [
      this.props.activeProjects,
      this.props.inactiveProjects
    ],
    [0,1],
    [
      this.props.activeProjects.keySeq().toArray(),
      this.props.inactiveProjects.keySeq().toArray()
    ]
  )
}

componentWillReceiveProps = (nextProps) => {
  this.setState({dataSource: this.cloneDataSource(this.state.dataSource)})
}

我需要调用克隆函数两次,这让我很担心。为什么在componentWillReceiveProps克隆数据还不够?

您不能只使用
componentWillReceiveProps
,因为它和您必须使用
nextProps
,而不是
this.props
。如果您的
列表视图
的数据作为
道具
来自顶部,您总是需要两个点来更新
列表视图.数据源
。一个用于初始渲染,另一个用于即将到来的更新。保持干燥的一种方法是:

constructor(props) {
  super(props);

  this.state = {
    // You can initialize it directly on to the state object
    dataSource: new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2,
      getRowData: (dataBlob, sectionId, rowId) => dataBlob[sectionId].get(rowId),
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2
    }),
  };
}

componentWillMount() { // Or `componentDidMount`
  // 1. For initial render (note: I'm passing this.props, you'll see why on 2.)
  this.updateDataSource(this.props);
}

componentWillReceiveProps(nextProps) {
  // 2. For updates
  // (note: you must pass `nextProps` because 
  // `this.props` has not been updated)
  this.updateDataSource(nextProps); 
}

// Do your thing
updateDataSource(data) {
  this.setState({
    dataSource: this.state.dataSource.cloneWithRowsAndSections(
      [
        data.activeProjects,
        data.inactiveProjects
      ],
      [0, 1],
      [
        data.activeProjects.keySeq().toArray(),
        data.inactiveProjects.keySeq().toArray()
      ]
    )
  });
}
编辑


另外,您应该注意,并非所有的
道具都将出现在
nextrops
中,因为只有更改的道具才会出现在
newProps
中,因此您应该正确处理,确保道具字段确实存在。

太好了,谢谢。做两次感觉有点不对劲,但现在我知道为什么了就没事了。实际上,我一开始在componentWillUpdate中使用了数据克隆,但我将其移动到了构造函数中,以便在创建数据源的地方使用它。这也是为什么我在一个单独的变量中初始化它(不是在这个.state中),这样我就可以以一种干净的方式将它发送到克隆函数。重构也是我丢失“nextrops”的地方。谢谢你抓到了。关于你的编辑:你的意思是我需要在更新函数的顶部有这样的东西吗:if(!data)return;data.activeProjects=data.activeProjects | | this.props.activeProjects;data.inactiveProjects=data.inactiveProjects | | this.props.inactiveProjects;是的,没错。但是,我认为您不需要检查
数据是否存在。它将存在,否则生命周期回调将永远不会被调用(不是100%确定,但它会有意义)。非常感谢。你帮了大忙。现在我可以更加自信地继续走这条路了。
constructor(props) {
  super(props);

  this.state = {
    // You can initialize it directly on to the state object
    dataSource: new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2,
      getRowData: (dataBlob, sectionId, rowId) => dataBlob[sectionId].get(rowId),
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2
    }),
  };
}

componentWillMount() { // Or `componentDidMount`
  // 1. For initial render (note: I'm passing this.props, you'll see why on 2.)
  this.updateDataSource(this.props);
}

componentWillReceiveProps(nextProps) {
  // 2. For updates
  // (note: you must pass `nextProps` because 
  // `this.props` has not been updated)
  this.updateDataSource(nextProps); 
}

// Do your thing
updateDataSource(data) {
  this.setState({
    dataSource: this.state.dataSource.cloneWithRowsAndSections(
      [
        data.activeProjects,
        data.inactiveProjects
      ],
      [0, 1],
      [
        data.activeProjects.keySeq().toArray(),
        data.inactiveProjects.keySeq().toArray()
      ]
    )
  });
}