Skip to content

Commit

Permalink
Refactor: 'VehiclesList' component to handle static vehicle data
Browse files Browse the repository at this point in the history
- Added static vehicle list to manage delays in database fetching.
- Included timeout to handle database initialization delay for
  a better user experience.
- Updated useEffect dependencies for better component re-rendering.
- Enhanced error handling with 'DataStatusDialog' component.
  • Loading branch information
ITurres committed Apr 4, 2024
1 parent 2cadbb5 commit 23745c7
Showing 1 changed file with 75 additions and 35 deletions.
110 changes: 75 additions & 35 deletions src/features/vehicles/VehiclesList.jsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,107 @@
import React, { useEffect, useCallback } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import Spinner from 'react-bootstrap/Spinner';
import { FaSpinner } from 'react-icons/fa6';

import SplideCarousel from './SplideCarousel';
import { fetchVehicles } from './vehiclesThunk';

import '../../styles/features/vehicles/VehiclesList.scss';
import DataStatusDialog from '../../components/DataStatusDialog';

const VehiclesList = () => {
function VehiclesList() {
const dispatch = useDispatch();
const { loading, error, vehiclesList } = useSelector(
(state) => state.vehicles,
);

const [staticVehicleList, setStaticVehicleList] = useState([]);
const [databaseOnDelay, setDatabaseOnDelay] = useState(false);

// ? useCallback to avoid creating a new function on every render
// ? since useEffect uses the function as a dependency.
const reFetchVehicles = useCallback(() => {
dispatch(fetchVehicles());
}, [dispatch]);

useEffect(() => {
reFetchVehicles();
}, [reFetchVehicles]);
// ! The inclusion of 'staticVehicleList' in the dependency array ensures that
// ! the details page displays correctly when a vehicle is selected.
// * This is because, when the 'staticVehicleList' is updated, it also resets
// * the 'vehicle' state to null, allowing for the selection of a new vehicle.
// ! This behavior is specific to the handling of static vehicle data,
// * ensuring that the component re-renders with the appropriate data
// * (dynamic or static) each time a vehicle is selected.
}, [reFetchVehicles, staticVehicleList]);

const { loading, error, vehiclesList } = useSelector(
(state) => state.vehicles,
);
// * Where the database is currently hosted, it takes a few seconds to
// * initialize and become active. This useEffect hook will check if the
// * initial fetch for the vehicles list is still loading
// * after X seconds, if so it will fetch the static vehicle list from
// * the JSON file which then will be rendered at the 'if (databaseOnDelay) {}' block.
// * for a better user experience.
useEffect(() => {
const timeout = setTimeout(() => {
if (loading) {
setDatabaseOnDelay(true);
}
}, 3000);

if (loading) {
return () => clearTimeout(timeout);
}, [loading]);

useEffect(() => {
if (databaseOnDelay) {
import('../../json/vehicles.json')
.then((module) => {
setStaticVehicleList(module.data);
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error('An error occurred while importing the module:', error);
});
}
}, [databaseOnDelay]);

if (loading && databaseOnDelay) {
return (
<div className="loading-error-wrapper">
<Spinner animation="grow" variant="danger" />
<p>
The project database is currently hosted on Render.com and is in a
dormant state. Kindly allow a few moments for the database to
initialize and become active.
</p>
<h3>Loading...</h3>
</div>
<>
<div className="vehicles__list--wrapper">
<SplideCarousel vehiclesList={staticVehicleList} />
</div>

<DataStatusDialog reFetchFunction={reFetchVehicles} />
</>
);
}

if (error) {
const isCentered = true;
return (
<div className="loading-error-wrapper">
<h3>Sorry, something went wrong...</h3>
<button type="button" className="btn" onClick={reFetchVehicles}>
Refresh
</button>
<DataStatusDialog
isCentered={isCentered}
paragraph="An error occurred while getting the updated list of vehicles.
We are sincerely sorry for the inconvenience."
strongText="Please try again later."
status="Error"
reFetchFunction={reFetchVehicles}
/>
);
}

if (!loading && vehiclesList.length > 0) {
return (
<div className="vehicles__list--wrapper">
<SplideCarousel vehiclesList={vehiclesList} />
</div>
);
}

return vehiclesList.length > 0 ? (
return (
<div className="vehicles__list--wrapper">
<SplideCarousel vehiclesList={vehiclesList} />
</div>
) : (
<div className="loading-error-wrapper">
<h3>No vehicles found</h3>
<button type="button" className="btn" onClick={reFetchVehicles}>
Refresh
</button>
<div className="loader-indicator visible">
<FaSpinner />
</div>
</div>
);
};
}

export default VehiclesList;

0 comments on commit 23745c7

Please sign in to comment.