簡體   English   中英

React-Native更新列表視圖數據源

[英]React-Native Updating List View DataSource

我有一個iOS應用程序,我正在使用react-native。 Game類包含一個ListView組件。 我在構造函數中設置狀態並包含一個dataSource 我現在有一個硬編碼的數據數組,我存儲在一個不同的狀態屬性( this.state.ds )。 然后在componentDidMount我使用cloneWithRows方法克隆this.state.ds作為視圖的dataSource。 就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的對象this.state.dataSource._dataBlob.s1 通過進一步調試,我發現由於其他數組已經發生變化,ListView的DataSource對象無法識別更改,因為當我設置狀態並rowHasChanged ,它所克隆的數組與數組this.state.dataSource._dataBlob.s1匹配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中的原始數組進行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和datasource)。

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足夠聰明,可以檢測dataSource中的更改以及是否應該重新呈現列表。 如果要更新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上閱讀有關類似問題的更多信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM