As you can see here. I first make an API call to get my data usage from the server, and then I store the response I got from the server to dataUsage by setting setDataUsage. However, I never got the accurate usedPercent in "{ name: 'Used', data: usedPercent }", instead, I received a zero. How do I make sure this component takes the update and rerender once the API call has been finished?
const Piechart= () => {
const userContext = useContext(UserContext)
const history = useHistory()
const [dataUsage, setDataUsage] = useState({
upload: 0,
redundancy: 0,
usedData: 0,
downloaded: 0,
quoteData: 0,
rank: 0
});
const [usedPercent, setUsedPercent] = useState(0);
useEffect(() => {
API().get('/mydatausage')
.then(res => {
const usage = res.data;
setDataUsage({ upload:usage.up, redundancy:usage.red, usedData:usage.used,
downloaded:usage.dwn, quoteData:usage.quote, rank:usage.rnk });
}).catch(err => {
authErrorHandler(err, userContext.logoutHandler, history)
})
},[])
const bToGbIndex = 1073741824;
useEffect(
() => {
// if (componentDidUpdate & (x or y changed))
setUsedPercent(dataUsage.usedData / bToGbIndex / dataUsage.quoteData);
},
[dataUsage]
);
const unUsedPercent = 100 - usedPercent;
console.log(usedPercent)
console.log(unUsedPercent)
return(
<>
<Donut
chartData={[
{ name: 'Used', data: usedPercent },
{ name: 'Free', data: unUsedPercent }
]}
chartWidth={300}
chartHeight={500}
title="Your Data Usage"
chartThemeConfig={{
series: {
colors: ['#ffe0bd', '#670303', '#6cbfce'],
},
}}
/>
</>
);
}
export default Piechart
Your usedPercent
can just be a simple variable inside the component:
const usedPercent = dataUsage.quoteData ? (dataUsage.usedData / bToGbIndex / dataUsage.quoteData) : 0;
Or if you want to memoize it (it's optional), use the React useMemo hook:
const { usedData, quoteData } = dataUsage;
const usedPercent = useMemo(() => quoteData ? (usedData / bToGbIndex / quoteData) : 0, [usedData, quoteData]);
You don't need to have a separate useEffect
to update usedPercent
. Think about useEffect
as the old componentDidUpdate
/ componentDidMount
, while it's possible to do multiple things inside componentDidUpdate
, they shouldn't be dependent of each other. Avoid writing useEffect
statements those are dependent of others.
In fact, as your usedPercent
is derived / computed data from dataUsage
, you don't have to make it a stateful variable either. If you want to keep your React component simple and maintainable, always try to keep the number of stateful data to minimum.
Looks like you are using both usedPercent and unUsedPercent
while rendering the component.
<Donut chartData={[
{ name: 'Used', data: usedPercent },
{ name: 'Free', data: unUsedPercent }
]}
...
So when you get usedPercent
as zero then actaual state is not changed so component does not re-render\update.
Since you are using usedPercent and unUsedPercent
, I would create one state variable even for unUsedPercent
then your use effect should set this as below so that your component gets updated even when you get usedPercent as zero
const [unUsedPercent, setUnUsedPercent] = useState(0);
useEffect(
() => {
// if (componentDidUpdate & (x or y changed))
setUsedPercent(dataUsage.usedData / bToGbIndex / dataUsage.quoteData);
const unUsedPercent = 100 - usedPercent;
serUnUnsedPercent(unUsedPercent);
},
[dataUsage]
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.