Reputation: 73
scenario:
I have two api calls, and they both contribute to the same state, so what I did originally was just await two api calls in the same useEffect. However, one of them is a fairly slow one, so I need to wait extra long time for the page rendering.
const [loading, setLoading] = useState(true)
useEffect(async() => {
try{
slow_api_call_promise = await slow_api_call
quick_api_call_promise = await quick_api_call
setLoading(false)
let newState = quick_api_call_promise.data.merge(slow_api_call_promise.data)
setState(newState)
}catch(e){
setLoading(false)
//show error message
}
},[])
return <React.Fragment>
{loading ? <SpinnerComponent />: <Actual Page />}
</React.Fragment>
fortunately, the quick one actually provides most of the state I need for initial rendering, and the slow one contributes to just part of the page state. So for rendering experience, I separated them into two useEffect and set different loading state for them. It seems to work. but this looks silly to me, it is going to render twice. is there a better way, an optimized way to approach this.
const [loadingWhole, setLoadingWhole] = useState(true)
const [loadingPart, setLoadingPart] = useState(true)
useEffect(async() => {
quick_api_call_promise = await quick_api_call
setLoadingWhole(false)
},[])
useEffect(async() => {
slow_api_call_promise = await slow_api_call
setLoadingPart(false)
},[])
Upvotes: 0
Views: 2751
Reputation: 664630
Yes, you can keep a single effect, just do a first setState
already after you've fetched the quick response:
const [state, setState] = useState(null);
const [loadingWhole, setLoadingWhole] = useState(true);
const [loadingPart, setLoadingPart] = useState(true);
async function fetchResults() {
const quickResult = await callQuickApi();
setState(quickResult.data);
setLoadingPart(false);
const slowResult = await callSlowApi();
let newState = merge(quickResult.data, slowResult.data);
setState(newState);
setLoadingWhole(false);
}
useEffect(async() => {
fetchResults().catch(err => {
setLoadingPart(false);
setLoadingWhole(false);
//show error message
});
},[]);
Btw, instead of 4 separate useState
hooks you might want to consider using just one, which can be in 5 states only not a multitude of combinations (even !loadingWhole && loadingPart
that doesn't make sense):
Upvotes: 1