I am writing a component in ReactJS. The component shows the multiple card in 3 column. To show data in this card I have taken one state variable named data
.
This state variable is set by 4 useEffect. Because the data is not from one single API. To show data in card required to have 4 APIs to consume. Now the issue is with the synchronisation of useEffect for the data variable.
Following is the code:
import { Box, Typography } from '@mui/material';
import StudyMonitoringCard from '@components1/k8s/common/StudyMonitoringCard';
import { useEffect, useState } from 'react';
import { getUserSession } from '@lib/auth';
import apiMonitoring from '@api1/monitoring';
import Loader from '@components1/common/Loader';
import apiStudy from '@api1/Study';
import { ApplicationStats } from 'src/utils/common';
interface MonitorData {
name: string;
studyname: string;
span_id: string;
account_name: string;
account_id: string;
ready_pods: number;
total_pods: number;
}
const Monitoring: React.FC = () => {
const [data, setData] = useState<ApplicationStats[]>([]);
const [uniqueAcc, setUniqueAcc] = useState<string[]>([]);
const [completedRelay, setCompletedRelay] = useState<boolean>(false);
const [completedEvent, setCompleteEvent] = useState<boolean>(false);
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
useEffect(() => {
setErrorMessage('');
setLoading(true);
const user = getUserSession();
apiMonitoring
.listMonitoringWorkload(user.tenant?.id as string)
.then((res) => {
setLoading(false);
const monitoring = res?.data?.data?.k8s_workloads_cloud_account_monitoring_v2?.rows;
const error = res?.data.errors;
if (monitoring && monitoring.length > 0) {
const data = monitoring.map((m: MonitorData) => ({
name: m.name,
studyname: m.studyname,
accountName: m.account_name,
accountId: m.account_id,
workloadId: m.span_id,
nrequests: null,
nerrors: null,
nerrorscritical: null,
nevents: null,
neventscpu: null,
neventsmemory: null,
cpu: null,
mem: null,
latency: null,
rtt: null,
optimize: '-',
readyPods: m.ready_pods,
totalPods: m.total_pods,
}));
const uniqueAcc = [...new Set(data.filter((b: any) => b.accountId).map((item: any) => item.accountId))];
setData(data);
setUniqueAcc(uniqueAcc as string[]);
} else if (error && error.length > 0) {
setData([]);
setErrorMessage('Failed to fetch Monitoring');
} else {
setData([]);
}
})
.catch((err) => {
console.log(err);
setLoading(false);
setErrorMessage('Failed to fetch Monitoring');
});
}, []);
useEffect(() => {
if (data == undefined || data.length == 0) {
return;
}
for (const value of uniqueAcc) {
const applicationArray = data
.filter((b: any) => b.accountId == value)
.map((b: any) => ({
name: b.name,
studyname: b.studyname,
}));
const request = {
no_sinks: true,
body: {
account_id: value,
action_name: 'application_stats',
action_params: { applications: JSON.stringify(applicationArray) },
},
cache: false,
};
apiStudy
.hitRelayServer(request)
.then((res: any) => {
const statsData = res?.data?.data || [];
if (statsData && statsData.length > 0) {
const updatedStats = data.map((obj1: any) => {
const matchingObj = statsData.find((obj2: any) => obj1.name == obj2.name && obj1.studyname == obj2.studyname);
if (matchingObj) {
return {
...obj1,
cpu: matchingObj?.cpu_p99,
memory: matchingObj?.memory_p99,
nrequests: matchingObj?.total_request_count,
latency: matchingObj?.latency,
nerrors: matchingObj?.failure_request_count,
nerrorscritical: matchingObj?.log_failure_count,
maxCPUReq: matchingObj?.max_cpu_request,
maxMemoryReq: matchingObj?.max_memory_request,
maxMemoryUsage: matchingObj?.memory_max,
};
} else {
return obj1;
}
});
setData(updatedStats);
}
})
.catch((err) => {
console.log('failed to fetch app monitoring- ', err);
});
}
setCompletedRelay(true);
}, [uniqueAcc]);
useEffect(() => {
if (data == undefined || data.length == 0 || !completedRelay) {
return;
}
listMonitoringWorkloadEventCount();
}, [completedRelay]);
useEffect(() => {
if (data == undefined || data.length == 0 || !completedEvent) {
return;
}
listMonitoringWorkloadRecommendationCount();
}, [completedEvent]);
const listMonitoringWorkloadEventCount = () => {
const user = getUserSession();
apiMonitoring
.listMonitoringWorkloadEventCount(user.tenant?.id as string)
.then((res) => {
const workloadEventCountRes = res?.data?.data?.k8s_workloads_cloud_account_monitoring_events_v2?.rows || [];
if (workloadEventCountRes && workloadEventCountRes.length > 0) {
const updatedStats = data.map((obj1: any) => {
const matchingObj = workloadEventCountRes.find(
(obj2: any) => obj1.accountId == obj2.cloud_account_id && obj1.name == obj2.name && obj1.studyname == obj2.studyname
);
if (matchingObj) {
return {
...obj1,
nevents: matchingObj?.event_count || '-',
};
} else {
return obj1;
}
});
setData(updatedStats);
}
setCompleteEvent(true);
})
.catch((err) => {
console.log(err);
setCompleteEvent(true);
});
};
const listMonitoringWorkloadRecommendationCount = () => {
const user = getUserSession();
apiMonitoring
.listMonitoringWorkloadRecommendationCount(user.tenant?.id as string)
.then((res) => {
const workloadRecommendationCountRes = res?.data?.data?.k8s_workloads_cloud_account_monitoring_recommendations_v2?.rows || [];
if (workloadRecommendationCountRes && workloadRecommendationCountRes.length > 0) {
const updatedStats = data.map((obj1: any) => {
const matchingObj = workloadRecommendationCountRes.find(
(obj2: any) => obj1.accountId == obj2.cloud_account_id && obj1.name == obj2.workload_name && obj1.studyname == obj2.studyname
);
if (matchingObj) {
return {
...obj1,
optimize: matchingObj?.recommendation_count || '-',
};
} else {
return obj1;
}
});
setData(updatedStats);
}
setCompletedRelay(false);
setCompleteEvent(false);
})
.catch((err) => {
console.log(err);
});
};
return (
<Box sx={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', margin: '0px -40px' }}>
{loading ? (
<Loader />
) : !loading && data.length > 0 ? (
data.map((item, index) => <StudyMonitoringCard data={item} key={index} />)
) : errorMessage ? (
<Typography>{errorMessage}</Typography>
) : (
<Typography>No Data For Monitoring</Typography>
)}
</Box>
);
};
export default Monitoring;
What I did (Disclaimer: which is NOT working) is I tool two boolean variable that if that variable set then consume a API.
What should be the ideal solution for this situation? Or Even is this correct to use useEffect like this?