react -原生更新列表视图数据源

React-Native Updating List View DataSource

本文关键字:视图 数据源 列表 更新 原生 react      更新时间:2023-09-26

我用react-native制作了一款iOS应用。Game类包含一个ListView组件。我在构造函数中设置状态,并包含一个dataSource。我现在有一个硬编码的数据数组,我存储在一个不同的状态属性(this.state.ds)。然后在componentDidMount中,我使用cloneWithRows方法克隆我的this.state.ds作为视图的数据源。就ListViews而言,这是非常标准的,而且工作得很好。下面是代码:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
 var React = require("react-native");
 var { StyleSheet, Text, View, ListView, TouchableHighlight } = React;
class Games extends React.Component {
constructor(props) {
    super(props);
    var ds = new ListView.DataSource({
        rowHasChanged: (r1, r2) => r1 != r2
    });
    this.state = {
        ds: [
            { AwayTeam: "TeamA", HomeTeam: "TeamB", Selection: "AwayTeam" },
            { AwayTeam: "TeamC", HomeTeam: "TeamD", Selection: "HomeTeam" }
        ],
        dataSource: ds
    };
}
componentDidMount() {
    this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this.state.ds)
    });
}
pressRow(rowData) {
    var newDs = [];
    newDs = this.state.ds;
    newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
    this.setState({
        dataSource: this.state.dataSource.cloneWithRows(newDs)
    });
}
renderRow(rowData) {
    return (
        <TouchableHighlight
            onPress={() => this.pressRow(rowData)}
            underlayColor="#ddd"
        >
            <View style={styles.row}>
                <Text style={{ fontSize: 18 }}>
                    {rowData.AwayTeam} @ {rowData.HomeTeam}{" "}
                </Text>
                <View style={{ flex: 1 }}>
                    <Text style={styles.selectionText}>
                        {rowData[rowData.Selection]}
                    </Text>
                </View>
            </View>
        </TouchableHighlight>
    );
}
render() {
    return (
        <ListView
            dataSource={this.state.dataSource}
            renderRow={this.renderRow.bind(this)}
        />
    );
}
}
var styles = StyleSheet.create({
 row: {
    flex: 1,
    flexDirection: "row",
    padding: 18,
    borderBottomWidth: 1,
    borderColor: "#d7d7d7"
},
selectionText: {
    fontSize: 15,
    paddingTop: 3,
    color: "#b5b5b5",
    textAlign: "right"
}
});

module.exports = Games

我遇到的问题是pressRow方法。当用户按下行时,我希望选择发生变化,并在设备上呈现变化。通过一些调试,我注意到,即使我在newDs数组中改变对象的Selection属性,在this.state.ds中的对象上也会发生相同的属性变化,并且类似地改变了this.state.dataSource._dataBlob.s1中的对象。通过进一步调试,我发现由于其他数组发生了变化,ListView的DataSource对象不能识别变化,因为当我设置状态并调用rowHasChanged时,它克隆的数组与数组this.state.dataSource._dataBlob.s1匹配,因此它看起来不像变化,也不呈现。

任何想法?

试试这个:

pressRow(rowData){
    var newDs = [];
    newDs = this.state.ds.slice();
    newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(newDs)
    })
}

这会生成一个数组的副本,然后可以独立于this.state.ds中的原始数组进行修改。

如果有人像我一样遇到这个问题,这里有一个完整的解决方案。

基本上,ListView组件似乎有一个错误,你需要重新构建数据源中更改的每个项目,以便ListView重新绘制它。

首先,创建数据源和数组的副本,并将它们保存为状态。在我的例子中,foods是数组。

constructor(props){
    super(props);
    var ds = new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
        dataSource: ds.cloneWithRows(foods),
        db: foods,
    };
}

当你想在数据源中改变一些东西时,复制你保存到状态的数组,用改变重建项目,然后用改变保存回状态的新数组(db和数据源)。

onCollapse(rowID: number) {
    console.log("rowID", rowID);
    var newArray = this.state.db.slice();
    newArray[rowID] = {
        key: newArray[rowID].key,
        details: newArray[rowID].details,
        isCollapsed: newArray[rowID].isCollapsed == false ? true : false,
    };
    this.setState({
        dataSource: this.state.dataSource.cloneWithRows(newArray),
        db: newArray,
    });
}

react足够智能,可以检测数据源中的变化,以及是否应该重新呈现列表。如果要更新listView,请创建新对象,而不是更新现有对象的属性。代码看起来像这样:

let newArray = this._rows.slice();
newArray[rowID] = {
  ...this._rows[rowID],
  Selection: !this._rows[rowID].Selection,
};
this._rows = newArray;
let newDataSource = this.ds.cloneWithRows(newArray);
this.setState({
  dataSource: newDataSource
});

你可以在Github上阅读更多类似的问题