Hey all,
While working on some performance improvements I found out that rowHasChanged
was not called in any of our lists. These lists are infinite-scrolling lists, meaning that when you reach the end, it will fetch more items to display and then dump them into the list.
It seems like all entries in the list are updated whenever we change the DataSource's content. We do have a shouldComponentUpdate
in place for all rows, but from how I understood rowHasChanged
, these rows would not needed to be rendered again.
I created a simple example that shows how we are appending items to the list: https://gist.github.com/janmonschke/c9c84b6050683da0c64f
What we basically do is:
constructor() {
// (...)
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => {
console.log('rowHasChanged');
return r1 !== r2;
}});
// (...)
}
onEndReached = () => {
// append data to the end
setData = [...setData, ...genRandomSet()];
this.setState({
dataSource: this.ds.cloneWithRows(setData)
});
console.log('onEndReached');
};
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
onEndReached={this.onEndReached}
/>
);
}
But rowHasChanged
is never logged.
Am I using it somehow in a wrong way? Are there better ways to append to a ListView?
Same behaviour in 0.18.0
and 0.19.0
Hey janmonschke, thanks for reporting this issue!
React Native, as you've probably heard, is getting really popular and truth is we're getting a bit overwhelmed by the activity surrounding it. There are just too many issues for us to manage properly.
react-native
or for more real time interactions, ask on Discord in the #react-native channel.Okay, found the solution in: http://stackoverflow.com/a/33871118.
Apparently it's important to clone from the correct DataSource instance ;)
So the code from the gist should have been:
setData = [...setData, ...genRandomSet()];
this.setState({
dataSource: this.state.dataSource.cloneWithRows(setData)
});
This seems like an error that's easily sneaking into your codebase. I wonder if the correct usage of DataSource
should be more emphasised in the documentation.
Thanks @janmonschke! I agree, I had a bunch of views constantly re-rendering and I couldn't figure out why that was happening and why the rowHasChanged
function was never getting called. 馃憡
Most helpful comment
Okay, found the solution in: http://stackoverflow.com/a/33871118.
Apparently it's important to clone from the correct DataSource instance ;)
So the code from the gist should have been:
This seems like an error that's easily sneaking into your codebase. I wonder if the correct usage of
DataSource
should be more emphasised in the documentation.