在React Native

时间:2016-09-24 08:36:44

标签: react-native

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

目前,我正如下面那样做。它有效,但在我的所有列表中采用这个概念之前,我想要一些输入。这是一个很好的方式吗?我的原始数据存在于Immutable.List中。

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

在构造函数中,我使用dataSource初始化this.state,我还使用单独的函数(cloneDataSource)执行数据的初始克隆:

constructor(props) {
  super(props);

  let dataSource = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2,
      getRowData: (dataBlob, sectionId, rowId) => dataBlob[sectionId].get(rowId),
      sectionHeaderHasChanged : (s1, s2) => s1 !== s2
  })

  this.state = {
    dataSource: this.cloneDataSource(dataSource)
  }
}

从构造函数和componentWillReceiveProps中调用克隆数据行的函数。这个特殊的listView有两个硬编码部分:

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上克隆数据已经足够了?

1 个答案:

答案 0 :(得分:1)

您不仅可以使用componentWillReceiveProps,因为它doesn't run on the first render,您必须使用nextProps,而不是this.props。如果您的ListView数据来自props的顶部,那么您总是需要两个位置来更新ListView.DataSource。一个用于初始渲染,另一个用于更新。保持DRY-ish的一种方法是执行此操作:

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()
      ]
    )
  });
}

修改

此外,您应该注意,并非所有props都在nextProps中,因为只有更改过的道具位于newProps中,因此您应该正确处理以确保支柱字段实际存在。