I have a class component which loads a list of applications from an external API. It then runs an additional request for each application to ping it.
It fetches the applications fine. However, it only sometimes pings the applications (calls checkPing).
Here is the component:
import axios from "axios";
import React from "react";
class Applications extends React.Component<any, any> {
constructor() {
super({});
this.state = {
applications: []
}
}
async checkPing(applicationId : bigint) {
//
}
async getApplications() {
var component = this;
await axios.get(process.env.REACT_APP_API_URL + '/applications')
.then(async function (response) {
await component.setState({
applications: response.data,
});
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
for (let i = 0; i < component.state.applications.length; i++) {
await component.checkPing(component.state.applications[i].id);
}
}
async componentDidMount() {
await this.getApplications();
}
render() {
return (<div></div>)
}
}
export default Applications;
2
Answers
As mentioned in the comment,
You either need to move your for loop inside then block or you can use componentDidUpdate lifecycle hook. axios call is asynchronous and your for loop is currently not waiting for it to complete.
Here is the example of using componentDidUpdate
If you do not want to use componentDidUpdate then you can move for loop in then call like this.
The main issue here is probably that
setState()
will queue the state change and not directly apply it.setState()
does not return a promise. Meaning thatawait component.setState(...)
is useless. The only way to know when React is done updating the state is to use thecomponentDidUpdate()
hook.An implementation of this hook, using your example might look like this: