Search code examples
reactjsreact-nativestatebackground-colorreact-native-listview

Background color not re-rendering


In this example I am creating a ListView with a set of TouchableOpacity buttons. Only one of them should be highlighted at a time with blue color.

The expression to determine background color:

backgroundColor:rowData.key==this.state.selected?'blue':'transparent'

The problem is that the backgroundColor doesn't change, despite the render() method being called and the state being updated.

I even tried forceUpdate(), in that case it renders twice, but without updating the color.

Render method:

render() {
    console.log("RE-RENDER",this.state.selected);//GETS CALLED, STATE UPDATED
    return (
        <ListView
            dataSource={this.state.dataSource}
            keyboardShouldPersistTaps={true}
            renderRow={(rowData) =>
                rowData.visible &&
                    <TouchableOpacity
                        style={{backgroundColor:rowData.key==this.state.selected?'blue':'transparent'}}
                        onPress={(evt) => {
                            this.setState({
                                selected:rowData.key,
                            }, function() {
                                console.log("NEW",this.state.selected);
                                this.forceUpdate();//DOESN'T HELP
                            });
                        }}
                    >
                        <Text>{rowData.value}</Text>
                    </TouchableOpacity>
                }
            automaticallyAdjustContentInsets={false}
        />
    );
};

Constructor:

constructor(props) {
    super(props);
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
        dataSource: ds.cloneWithRows([
            {
                key: 'first',
                value: 'BMW',
                visible: true,
            },{
                key: 'second',
                value: 'Mercedes',
                visible: true,
            },
        ]),
    };
}

Solution

  • The problem was that the ListView was not re-rendering, because the DataSource did not change. By adding the key property the update gets triggered every time the external key gets updated.

    render() {
        console.log("RE-RENDER",this.state.selected);//GETS CALLED, STATE UPDATED
        return (
            <ListView
                key={this.state.selected} // SOLVED MY PROBLEM
                dataSource={this.state.dataSource}
                keyboardShouldPersistTaps={true}
                renderRow={(rowData) =>
                    rowData.visible &&
                        <TouchableOpacity
                            style={{backgroundColor:rowData.key==this.state.selected?'blue':'transparent'}}
                            onPress={(evt) => {
                                this.setState({
                                    selected:rowData.key,
                                }, function() {
                                    console.log("NEW",this.state.selected);
                                    this.forceUpdate();//DOESN'T HELP
                                });
                            }}
                        >
                            <Text>{rowData.value}</Text>
                        </TouchableOpacity>
                    }
                automaticallyAdjustContentInsets={false}
            />
        );
    };