Reputation: 1021
I'm trying to refresh listview when componentWillReceiveProps executes. It seems dataSource is updated after fetching ( I put console.log(this.state.dataSource) in the render() and it changes according to the endpoint's current status. )
However, the ListView stays as same. I was wondering why and was suspicious of dataSource. So I ended up making string object to print out the dataSource in the render(). var str = JSON.stringify(this.state.dataSource._dataBlob.s1);
And <View><Text>{str}</Text>
The above part changes when componentWillReceiveProps() executed. However, the listview stays as same. I'm having no clue why this happens.
Here is the snippet of my code.
componentWillReceiveProps(){
var query = ApiUrl.urlForWeekInfo(this.state.email);
console.log(query);
this._executeQuery(query,3);
}
constructor(props) {
super(props);
var dataSource = new ListView.DataSource(
{rowHasChanged: (r1, r2) => r1.guid !== r2.guid});
this.state = {
isLoading: false,
...
first_name: this.props.first_name,
email: this.props.email,
dataSource: dataSource.cloneWithRows(this.props.listings)
};
}
..
_executeQuery(query,i) {
this.setState({ isLoading: true });
fetch(query)
.then(response => response.json())
.then(json => this._handleResponse(json.response,i))
.catch(error =>
this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));
}
_handleResponse(response,i) {
this.setState({ isLoading: false , message: '' });
if (response.application_response_code.substr(0, 1) === '1') {
if(i==1){
this.props.navigator.push({
title: 'Apply',
component: Apply,
passProps: {listings: response.listings, times: response.timetable, week_num: this.state.week_num}
});
} else if (i==3){
var output = response.listings;
this.setState({
dataSource: this.state.dataSource.cloneWithRows(output)
});
console.log(response.listings);
this.forceUpdate();
}
} else {
}
}
render() {
console.log(this.state.dataSource._dataBlob.s1);
var str = JSON.stringify(this.state.dataSource._dataBlob.s1);
var listviewsource = this.state.dataSource;
return (
<View style={[this.border('red'), styles.container_top]}>
<View style={[this.border('black'), styles.container_top_buttons]} >
<ListView
dataSource={listviewsource}
renderRow={this.renderRow.bind(this)}/>
</View>
{spinner}
<View>
<Text>{str}</Text>
</View>
</View>
);
}}
Please share any idea or experience you might have.
I ended up finding a solution for this issue:
var array = response.listings;
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
//=> call another ds variable.
this.setState({
rawData: array,
dataSource: ds.cloneWithRows(response.listings)
});
Upvotes: 0
Views: 762
Reputation: 3912
There is no direct method to update rows to your ListView. There is not much documentation on ListView.DataSource
out there. So here it goes-
If you want to add/append/prepend/update/delete rows from a ListView, all you have to do is just update the dataSource and call cloneWithRows() in setState.
For eg. I want to fetch data from a URL. Each time I hit "Load more", I append new rows to my data source.
getInitialState: function(){
return {
rawData: [],
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
}),
loaded: false,
page: 1,
}
},
At the very first time, I call this function in ComponentDidMount() which populates my ListView with initial data and "page"=1 in the state.
reloadData: function(){
this.setState({ loaded: false, rawData: [], page: 1 });
API.getUpcomingMovies(this.state.page)
.then((data) => {
this.setState({
rawData: this.state.rawData.concat(data),
dataSource: this.state.dataSource.cloneWithRows(this.state.rawData.concat(data)),
loaded: true,
});
});
},
And every time I tap on "load more" to get JSON from the API, I call the following function. Where "page" is incremented every time I hit "load more".
fetchData: function(){
this.setState({ loaded: false, page: this.state.page+1 });
API.getUpcomingMovies(this.state.page)
.then((data) => {
this.setState({
rawData: this.state.rawData.concat(data),
dataSource: this.state.dataSource.cloneWithRows(this.state.rawData.concat(data)),
loaded: true,
});
});
},
As you can see, I am concatenating my rawData[] (which is a simple array holding JSON objects). If you want to prepend new data to your rawData, you can do something like this-
this.setState({
rawData: data.concat(this.state.rawData)
)}
Upvotes: 1