Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native ListView not updating on data change

I'm not sure why the ListView isn't updating when my data changes. I've striped my code down to make it easy to read and created a rnplay:

https://rnplay.org/apps/ivG0mg

What I expect to happen is, the user clicks the list item and the row's bool isCollapsed is toggled making the background red. What actually happens is the datasource is updated but the list view doesn't recognize the change and nothing new is rendered. Any ideas?

'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);
like image 385
Dev01 Avatar asked Oct 30 '15 00:10

Dev01


1 Answers

Here's a link to a working version:

https://rnplay.org/apps/GWoFWg

These are the changes I need to make to fix it:

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

and this:

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,
    });
}
like image 159
Dev01 Avatar answered Jan 03 '23 16:01

Dev01