I've been banging my head against my desk for the past hour trying to figure out why the following code only displays the loading spinner and never updates to show the actual data even when I can see the data logged in the console, so I know the data is actually being fetched.
What is supposed to happen is that the page will display a spinner loader the first time the data is retrieved and then after useSWR
has finished getting the data, the page will re-render to show the data. The data will eventually be shown in like a globe thing, but just as a prototype, I'm rendering it just with .map
. The page is also not supposed to show the spinner a second time.
I think my problem might have something to do with calling the function to update the hook at the very end causes the whole page to re-render, although I'm not sure and if that is the case, I couldn't figure out how I'd make that work considering how SWR spontaneously re-fetches the data.
Here's the primary file:
import { useEffect, useState } from "react";
import Navbar from "@components/navbar";
import Globe from "@/components/interest-globes/globe";
import usePercentages from "@/components/interest-globes/globe-percentages";
const globeName = "primary";
const App = () => {
const [globePercentages, setGlobePercentages] = useState([]);
const [isFirstLoad, setFirstLoad] = useState(false);
const [isLoading, setLoading] = useState(false);
const [isError, setError] = useState();
useEffect(() => {
setFirstLoad(true);
}, []);
let {
globePercentages: newGlobePercentages,
isLoading: newLoadingState,
isError: newErrorState,
} = usePercentages(globeName);
console.log(newGlobePercentages, newLoadingState, newErrorState);
useEffect(() => {
updateGlobe();
}, [newGlobePercentages, newLoadingState, newErrorState]);
const updateGlobe = () => {
if (
isFirstLoad &&
(newGlobePercentages !== null || newGlobePercentages !== "undefined")
) {
setFirstLoad(false);
} else if (newLoadingState || !newGlobePercentages) {
setLoading(true);
return;
} else if (newErrorState) {
setError(newErrorState);
return;
}
setGlobePercentages(newGlobePercentages);
};
return (
<div>
<Navbar />
<div className="container-md">
<h1>The percentages are:</h1>
<br />
<Globe
globePercentages={globePercentages}
isLoading={isLoading}
isError={isError}
/>
{/* <Globe props={{ globePercentages, isLoading, isError }} /> */}
<br />
</div>
</div>
);
};
export default App;
Here is the globe component:
import Loading from "@components/loading";
import Error from "@components/error";
const Globe = ({ globePercentages, isLoading, isError }) => {
// const Globe = ({ props }) => {
// let { globePercentages, isLoading, isError } = props;
if (isLoading) {
return <Loading/>
}
else if (isError) {
return <Error/>
}
return (
<div>
{globePercentages.map((interest) => (
<div key={interest.name}>
<h2>Name: {interest.name}</h2>
<h4>Globe Percentage: {interest.globePercentage}%</h4>
<br />
</div>
))}
</div>
);
};
export default Globe;
Here is use-percentages:
import { useEffect } from "react";
import useSWR from "swr";
import fetcher from "@components/fetcher";
const usePercentages = (globeName) => {
const url = `/api/v1/interest-globes/${globeName}/get-globe-percentages`;
let { data, error } = useSWR(url, fetcher, { refreshInterval: 1000 });
return {
globePercentages: data,
isLoading: !error && !data,
isError: error,
};
};
export default usePercentages;