gtfs-display/src/pages/overview.js

136 lines
4.9 KiB
JavaScript

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import OverviewTable from '../components/overview-table';
import config from '../config';
export default function Overview() {
/* store data in function component state */
/* initialise as empty array */
const [overview, setOverview] = useState([]);
const [agencies, setAgencies] = useState(false);
const [wait, setWait] = useState(false);
const handleAsyncOps = async (isMounted) => {
/* get data for each agency */
for (let j = 0; j < overview.length; j++) {
// console.log('j: ' + j);
let isBreaking = false;
// 1. Make a shallow copy of the objects
const aryObjs = [...overview];
/// ///console.log('aryObjs len: ' + aryObjs.length);
// 2. Make a shallow copy of the object you want to mutate
const obj = { ...aryObjs[j] };
// 3. Replace the property you're intested in
const agencyId = obj.agency_id;
/// /console.log('agencyId: ' + agencyId);
let routeCount = obj.route_count;
// console.log('routeCount: ' + routeCount);
if (routeCount === null) {
const resRouteCount = await axios.get(
`${config.API}route-count?agencyid=${agencyId}`,
);
obj.route_count = resRouteCount.data;
routeCount = obj.route_count;
// console.log('routeCount: ' + routeCount);
isBreaking = true;
}
let tripCount = obj.trip_count;
// console.log('tripCount: ' + tripCount);
if (tripCount === null) {
const resTripCount = await axios.get(
`${config.API}trip-count?agencyid=${agencyId}`,
);
obj.trip_count = resTripCount.data;
tripCount = obj.trip_count;
// console.log('tripCount: ' + tripCount);
isBreaking = true;
}
// 4. Put it back into the array. N.B. we *are* mutating the array here, but that's why we made a copy first
aryObjs[j] = obj;
if (isBreaking && isMounted) {
// 5. Set the state to the new copy
setOverview((overview) => aryObjs);
setWait((wait) => !wait);
break;
}
}
};
const getAgencies = async (isMounted) => {
try {
/* get agencies */
/* TODO handle errors: https://www.valentinog.com/blog/await-react/ */
const res = await axios.get(`${config.API}agency-all`);
const aryOv = res.data;
for (let i = 0; i < aryOv.length; i++) {
const agencyId = aryOv[i].agency_id;
const agencyName = aryOv[i].agency_name;
const objOvItem = {};
objOvItem.agency_id = agencyId;
objOvItem.agency_name = agencyName;
objOvItem.route_count = null;
objOvItem.trip_count = null;
objOvItem.day = null;
/* set state */
if (isMounted) {
// TODO Study! Is objOvitem added to array overview?
setOverview((overview) => [...overview, objOvItem]);
}
}
/* set... is an async function and you cannot get the state value immediately after update. Use useEffect hook instead */
setAgencies((agencies) => !agencies);
} catch (err) {
console.error(`err.message: ${err.message}`);
}
};
useEffect(() => {
/* declare let isMounted = true inside useEffect, which will be changed in the cleanup callback, as soon as the component is unmounted. Before state updates, check this variable conditionally. */
let isMounted = true;
if (wait) {
setWait((wait) => !wait);
handleAsyncOps(isMounted);
}
return () => {
isMounted = false;
};
}, [wait]);
/* If you want to get an updated state value then use useEffect hook with dependency array. React will execute this hook after each state update. */
useEffect(() => {
/* declare let isMounted = true inside useEffect, which will be changed in the cleanup callback, as soon as the component is unmounted. Before state updates, check this variable conditionally. */
let isMounted = true;
/// ///console.log('useEffect() agencies: ' + agencies);
if (agencies) {
/// /console.log('agencies available');
handleAsyncOps(isMounted);
} else {
/// /console.log('agencies not available');
}
return () => {
isMounted = false;
};
}, [agencies]);
/* this hook is run after a DOM update. Changing state might result in an infinite loop */
/* hook need to be placed in body of the function component in which it is used */
useEffect(() => {
/* declare let isMounted = true inside useEffect, which will be changed in the cleanup callback, as soon as the component is unmounted. Before state updates, check this variable conditionally. */
let isMounted = true;
getAgencies(isMounted);
return () => {
isMounted = false;
};
/* use an empty dependency array to ensure the hook is running only once */
/* TODO study dependency array: https://reactjs.org/docs/hooks-effect.html */
}, []);
return <OverviewTable overview={overview} />;
}