I'm trying to use immutability-helper
to update my React state asynchronously from multiple sources (API calls). However, it seems to me that this is not the way to go, since state always gets updated with values from a single source only. Can someone explain me why is this the case and how to properly handle updates of my state?
import React from 'react';
import update from 'immutability-helper';
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
updateInterval: 60, // in seconds
apiEndpoints: [
'/stats',
'/common/stats',
'/personal/stats',
'/general_info',
],
items: [
{ itemName: 'One', apiUrl: 'url1', stats: {} },
{ itemName: 'Two', apiUrl: 'url2', stats: {} },
],
};
this.fetchData = this.fetchData.bind(this);
}
componentDidMount() {
this.fetchData();
setInterval(() => this.fetchData(), this.state.updateInterval * 1000);
}
fetchData() {
this.state.apiEndpoints.forEach(endpoint => {
this.state.items.forEach((item, i) => {
fetch(`${item.apiUrl}${endpoint}`)
.then(r => r.json())
.then(res => {
// response from each endpoint contains different keys.
// assign all keys to stats object and set default 0 to
// those which don't exist in response
const stats = {
statsFromFirstEndpoint: res.first_endpoint ? res.first_endpoint : 0,
statsFromSecondEndpoint: res.second_endpoint ? res.second_endpoint : 0,
statsFromThirdEndpoint: res.third_endpoint ? res.third_endpoint : 0,
};
this.setState(update(this.state, {
items: { [i]: { $merge: { stats } } }
}));
})
.catch(e => { /* log error */ });
});
});
}
render() {
return (
<div className="App">
Hiya!
</div>
);
}
}
export default App;
You should use the prevState
argument in setState
to make sure it always use the latest state:
this.setState(prevState =>
update(prevState, {
items: { [i]: { $merge: { stats } } },
}));
Alternatively, map your requests to an array of promises then setState
when all of them resolved:
const promises = this.state.apiEndpoints.map(endPoint =>
Promise.all(this.state.items.map((item, i) =>
fetch(), // add ur fetch code
)));
Promise.all(promises).then(res => this.setState( /* update state */ ));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.