I have been trying to understand how I could manage to make a ListView that can recieve often new data and push it to the front. With the code below, the list does not reflect change correctly, instead of having a new row at the top, the last one is beeing duplicated..
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
TouchableHighlight,
} = React;
var listview = React.createClass({
rows: [],
_rowHasChanged: function (r1, r2) {
// if (r1 !== r2)
// console.log('rowChanged', r1, r2);
// else
// console.log('row didn\'t Changed', r1, r2);
return r1 !== r2;
},
getInitialState: function() {
return {
dataSource: new ListView.DataSource({rowHasChanged: this._rowHasChanged}),
};
},
componentDidMount: function () {
this.rows = [
{id: 0, text: '0: text'},
{id: 1, text: '1: text'},
{id: 2, text: '2: text'},
{id: 3, text: '3: text'},
];
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.rows),
});
},
pushTopRow: function () {
var id = this.rows.length;
this.rows.unshift({id: id, text: id + ': text'});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.rows),
});
},
render: function() {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text key={rowData.id}>{rowData.text}</Text>}
/>
<TouchableHighlight
onPress={this.pushTopRow}>
<Text>PUSH TOP</Text>
</TouchableHighlight>
</View>
);
},
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'orange',
},
});
AppRegistry.registerComponent('listview', () => listview);
then I tried:
pushTopRow: function () {
var id = this.rows.length;
var newRow = [{id: id, text: id + ': text'}];
this.rows = newRow.concat(this.rows);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.rows),
});
},
this actually works, but I don't understand why first method doesn't work. I'm trying to figure out what is the best practises for handling with ListView:
kind of lacking of documentations and exemples, it would be great to clarify it for me and anyone. thanks you & have a good code day.
ListView assigns component keys by data source index, and consequently will rerender all rows whenever the datasource is prepended to. If your row data has any unique id, you can create a modified ListView that uses that as the key. See for example PrependableListView which will use the id attribute on your row data.
Note: this component is not generalized and will fail if there is no id property defined.
Note: I realize this does not answer your whole question, just a specific peculularity about prepending to the datasource.
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