React Native ListView: Rows are not re-rendering after datasource state has changed.
Here is a simplified version of my code:
render(): {
return <ListView
dataSource={this.state.DS}
renderRow={this.renderRow}/>
}
renderRow(item): {
return <TouchableOpacity onPress={() => this.handlePress(item)}>
{this.renderButton(item.prop1)}
</TouchableOpacity>
}
renderButton(prop1): {
if (prop1 == true) {
return <Text> Active </Text>
} else {
return <Text> Inactive </Text>
}
}
handlePress(item): {
**Change the prop1 of *item* in an array (clone of dataSource), then**
this.setState({
DS: this.state.DS.cloneWithRows(arrayFromAbove)
})
}
According to Facebook's example, ListView is supposed to rerender every time data source is changed. Is it because I'm only changing a property of an item in data source? It seems like renderRow function is not re-rendering, but render() function is from datasource change.
Thank you.
🧐 Re-renders reason: state changesWhen a component's state changes, it will re-render itself. Usually, it happens either in a callback or in useEffect hook.
As we already saw before, React re-renders a component when you call the setState function to change the state (or the provided function from the useState hook in function components). As a result, the child components only update when the parent component's state changes with one of those functions.
A React component automatically re-renders whenever there is a change in state or props, it only takes a simple state update from anywhere in the code to automatically re-render UI elements. However, you may see cases where rendering depends on other data.
You can use React memo (or PureComponent if you use classes) on the components that you don't want to re-render (MainArea,Footer). This way when an update is forced by their parent they will first make a check if any of their props changed and if not (which is your case), re-render will be skipped.
react is smart enough to detect changes in dataSource and if the list should be re-rendered. If you want to update listView, create new objects instead of updating the properties of existing objects. The code would look something like this:
let newArray = this._rows.slice();
newArray[rowID] = {
...this._rows[rowID],
newPropState: true,
};
this._rows = newArray;
let newDataSource = this.ds.cloneWithRows(newArray);
this.setState({
dataSource: newDataSource
});
You can read more about similar issue on Github
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With