I have a dropdown which when changes calls api to fetch data using useEffect
hook:
const [selectedComplianceFilter, setComplianceFilter] = useState("all");
useEffect(() => {
if (selectedComplianceFilter === "all") {
fetchFullReport();
} else {
fetchReportByCompliance(selectedComplianceFilter);
}
}, [selectedComplianceFilter]);
<select
name="compliance"
className="custom-select w-auto"
onChange={e => setComplianceFilter(e.target.value)}
>
<option value="all">All</option>
{compliances.map((compliance, i) => (
<option key={i} value={compliance}>
{compliance}
</option>
))}
</select>
I have another useEffect
hook which calls another api which returns scan status
useEffect(() => {
fetchCompliances();
let intervalId;
getScanStatus(0);
fetchFullReport();
intervalId = setInterval(() => {
getScanStatus(intervalId);
}, 10000);
return () => {
componentDidUnmount.current = true;
clearInterval(intervalId);
};
}, []);
This is the function to fetch scan status:
const [scanStatus, setScanStatus] = useState("");
const [lastUpdated, setLastUpdated] = useState();
const [reports, setReports] = useState([]);
const getScanStatus = async intervalId => {
const resp = await API.get(SCAN_STATUS_URL);
if (resp && resp.status) {
const { scanStatus = "", lastModifiedDate = "" } = resp.data || {};
const isValidDate = moment(lastModifiedDate).isValid();
if (!componentDidUnmount.current) {
setScanStatus(scanStatus);
isValidDate && setLastUpdated(getFormattedDateTime(lastModifiedDate));
if (scanStatus === "COMPLETED") {
clearInterval(intervalId);
console.log("selectedComplianceFilter", selectedComplianceFilter); // <== returns old state i.e., 'all' but should be latest selected option.
if (selectedComplianceFilter === "all") {
fetchFullReport();
} else {
fetchReportByCompliance();
}
}
}
}
};
Now what happens is when page loads fetchFullReport();
renders the table. Now when the dropdown is changed fetchReportByCompliance();
is called to filter the table and table gets updated with fewer rows now.
Meanwhile getScanStatus
is called on every 10 second interval and as soon as the api returns status = 'COMPLETED'
and the interval is stopped and the table gets updated with new data (fetchFullReport();
) and all the table rows are back which is a weird behavior as dropdown filter still has selected option other than ALL
option. So, when new data arrives as soon as scan is completed to update the table I added an if condition to update table based on selectedComplianceFilter
value.
But when the getScanStatus
function api returns status = 'COMPLETED' the value of selectedComplianceFilter
is still 'all'
but the dropdown has another option selected. I am s assuming it is because of async await
block which still holds the previous value of selectedComplianceFilter
state.
How do I get the latest value of selectedComplianceFilter
state when getScanStatus
executes in the future as it is asynchronous?