I had a page which loaded a list of applications, then ran a request for each of those applications to ping them. I wanted to ensure this page updated the status on a periodic basis in the background.
I decided to add a setTimeout
to getApplications
, so it reloaded them every 30 seconds.
The issue is, the table I originally rendered in HTML doesn't update to reflect the changes to applications such as the name or ping status.
import axios from "axios";
import React from "react";
class Applications extends React.Component<any, any> {
constructor() {
super({});
this.state = {
applications: []
}
this.logout = this.logout.bind(this);
}
async pingApplications() {
for (const application of this.state.applications) {
await this.checkPing(application.id);
}
}
async componentDidUpdate(prevProps: any, prevState: any) {
if (this.state.isLoading) return;
if (this.state.error) return;
await this.pingApplications();
}
async checkPing(applicationId : number) {
console.log('[data-application-id=\'' + applicationId + '\']');
axios.get(process.env.REACT_APP_API_URL + '/applications/' + applicationId + '/ping')
.then(function (response) {
if (response.status == 404) {
document.querySelectorAll('[data-application-id=\'' + applicationId + '\']')[0].innerHTML = '<div class="h-2.5 w-2.5 rounded-full bg-green-500 mr-2"></div> Offline';
}
else {
document.querySelectorAll('[data-application-id=\'' + applicationId + '\']')[0].innerHTML = '<div class="h-2.5 w-2.5 rounded-full bg-green-500 mr-2"></div> Running';
}
})
.catch(function (error) {
document.querySelectorAll('[data-application-id=\'' + applicationId + '\']')[0].innerHTML = '<div class="h-2.5 w-2.5 rounded-full bg-red-500 mr-2"></div> Offline';
});
}
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++) {
console.log(i);
await component.checkPing(component.state.applications[i].id);
}
setTimeout(component.getApplications, 30000);
}
logout() {
localStorage.removeItem('access_token');
document.location.reload()
}
async componentDidMount() {
await this.getApplications();
}
render() {
return (<div className={"p-4"}>
<div className="flex">
<a href="/applications/create"
className="bg-green-500 hover:bg-green-400 text-white px-5 py-2 mb-6 rounded shadow text-center mr-4 block">
Create
</a>
<div className="bg-red-500 hover:bg-red-400 text-white px-5 py-2 mb-6 rounded shadow text-center"
onClick={this.logout}>
Logout
</div>
</div>
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500">
<thead className="text-xs text-gray-700 uppercase bg-gray-50">
<tr>
<th scope="col" className="px-6 py-3">
Name
</th>
<th scope="col" className="px-6 py-3">
Repository
</th>
<th scope="col" className="px-6 py-3">
Status
</th>
</tr>
</thead>
<tbody>
{this.state.applications.map(function(application: any, index: any) {
return (<tr key={index} className="bg-white border-b">
<th scope="row" className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
<a href={'/applications/' + application.id}>{application.name}</a>
</th>
<td className="px-6 py-4">
{application.repository.url.split("/").pop()}
</td>
<td className="px-6 py-4">
<div data-application-id={application.id} className="flex items-center">
<div className="h-2.5 w-2.5 rounded-full bg-orange-400 mr-2"></div>
Pinging...
</div>
</td>
</tr>);
})}
</tbody>
</table>
</div>
</div>)
}
}
export default Applications;