11

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);

2 Answers 2

11

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,
    });
}
Sign up to request clarification or add additional context in comments.

3 Comments

The link is not working anymore... could you please update? Thanks
using ...newArray[rowID] from es6 you can re-use all keys in newArray[rowID] obj.. and just add your changed key in the end
by this I need to set all the values what if I want to set only updated values?
2

Looked like this would be the solution you need React-Native Updating List View DataSource

But I played around with it a little and also couldn't get it working. https://rnplay.org/apps/sk_ukQ

Not sure if it will help, but I tried this setting the array as blank and am able to clear the entire list... this.setState({dataSource: this.state.dataSource.cloneWithRows([])});

I think for some reason it's using a cached version of the original array rather than the updated array. Just not sure why.

9 Comments

Thanks for the link. The answer was in the comments. I had to rebuild the item when making a change to it. Seems like a bug that I hope gets fixed at some point. rnplay.org/apps/GWoFWg
Ah, good! Glad I was at least able to point you in the right direction. Thanks for sharing the solution.
Also, you might be able to help this guy out... stackoverflow.com/questions/33436902/…
Just answered that question too. You're like the Robin Hood of stackoverflow. Getting questions answered right and left. :)
Ha, just connecting dots :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.