问题 React Native ListView不更新数据更改


我不确定为什么在我的数据发生变化时ListView没有更新。我已经将代码条带化,以便于阅读和创建一个rnplay:

https://rnplay.org/apps/ivG0mg

我期望发生的是,用户单击列表项和行的布尔值 isCollapsed 切换使背景变红。实际发生的是数据源已更新但列表视图无法识别更改并且未呈现任何新内容。有任何想法吗?

'use strict';

var React = require('react-native');

var {
    ScrollView,
    Text,
    Image,
    StyleSheet,
    TouchableHighlight,
    AppRegistry,
    View,
    ListView,
} = React;

var styles = StyleSheet.create({
    container: {
        flex: 1,
        flexDirection: 'column',
        padding: 15,
    },
    red: {
        backgroundColor: "red",
    }
});

var foods = [
    {key: 'Almond Milk (Homemade)', details:''},
    {key: 'Club Soda', details:'', isCollapsed: true},
    {key: 'Coconut Milk/Cream', details:''},
    {key: 'Coconut Water', details:''},
    {key: 'Coffee/Espresso', details:'', isCollapsed: true},
    {key: 'Fruit Juice', details:''},
    {key: 'Kombucha', details:''},
    {key: 'Mineral Water', details:''},
    {key: 'Unsweetened Tea', details:''},
    {key: 'Water', details:''},
    {key: 'Fruit Juice', details:''},
    {key: 'Kombucha', details:''},
    {key: 'Mineral Water', details:''},
    {key: 'Unsweetened Tea', details:''},
    {key: 'Water', details:''},
    {key: 'Fruit Juice', details:''},
    {key: 'Kombucha', details:''},
    {key: 'Mineral Water', details:''},
    {key: 'Unsweetened Tea', details:''},
    {key: 'Water', details:''},
    {key: 'Fruit Juice', details:''},
    {key: 'Kombucha', details:''},
    {key: 'Mineral Water', details:''},
    {key: 'Unsweetened Tea', details:''},
    {key: 'Water', details:''},
    {key: 'Fruit Juice', details:''},
    {key: 'Kombucha', details:''},
    {key: 'Mineral Water', details:''},
    {key: 'Unsweetened Tea', details:''},
    {key: 'Water', details:''},
];

class SampleApp extends React.Component{
    constructor(props){
        super(props);
        var ds = new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
        });
        this.state = {
            dataSource: ds.cloneWithRows(foods),
        };
    }
    _renderRow(data, sectionID, rowID) {
                return (
                        <TouchableHighlight 
                            style={[
                                    styles.container,
                                    data.isCollapsed && styles.red]}
                onPress={()=>this.onCollapse(rowID)}>
                <Text>{data.key}</Text>
            </TouchableHighlight>
        );
    }
    onCollapse(rowID: number) {
        console.log("rowID", rowID);
        foods[rowID].isCollapsed = !foods[rowID].isCollapsed;
        this.setState({dataSource: this.state.dataSource.cloneWithRows(foods)});
    }
    render() {
        return(
            <ListView
                style={styles.subContainer}
                dataSource={this.state.dataSource}
                renderRow={this._renderRow.bind(this)}
                initialListSize={15}/>
        )
    }
};

AppRegistry.registerComponent('SampleApp', () => SampleApp);

11865
2017-10-30 00:00


起源



答案:


这是一个工作版本的链接:

https://rnplay.org/apps/GWoFWg

这些是我需要做的修改来修复它:

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

和这个:

onCollapse(rowID: number) {
    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,
    });
}

11
2017-10-30 05:06



该链接不再有效...请您更新?谢谢 - chemitaxis
运用 ...newArray[rowID] 从es6你可以重新使用所有键 newArray[rowID]  obj ..并且最后添加您更改的密钥 - jose920405
通过这个我需要设置所有值,如果我只想设置更新的值? - Asnad Atta


答案:


这是一个工作版本的链接:

https://rnplay.org/apps/GWoFWg

这些是我需要做的修改来修复它:

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

和这个:

onCollapse(rowID: number) {
    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,
    });
}

11
2017-10-30 05:06



该链接不再有效...请您更新?谢谢 - chemitaxis
运用 ...newArray[rowID] 从es6你可以重新使用所有键 newArray[rowID]  obj ..并且最后添加您更改的密钥 - jose920405
通过这个我需要设置所有值,如果我只想设置更新的值? - Asnad Atta


看起来这将是您需要的解决方案 React-Native更新列表视图数据源

但我玩了一下它也无法使它工作。 https://rnplay.org/apps/sk_ukQ

不确定它是否会有所帮助,但我尝试将此数组设置为空白并且能够清除整个列表... this.setState({dataSource:this.state.dataSource.cloneWithRows([])});

我认为由于某种原因它使用原始数组的缓存版本而不是更新的数组。只是不确定为什么。


2
2017-10-30 04:16



谢谢你的链接。答案在评论中。我不得不在更改项目时重建项目。看起来像一个我希望在某些时候得到解决的bug。 rnplay.org/apps/GWoFWg - Tom Krones
啊好!很高兴我至少能指出你正确的方向。感谢您分享解决方案。 - Chris Geirman
此外,你可以帮助这个家伙... stackoverflow.com/questions/33436902/... - Chris Geirman
刚刚回答了这个问题。你就像堆栈溢出的罗宾汉。左右回答问题。 :) - Tom Krones
哈,只是连接点:) - Chris Geirman