Search code examples
javascriptreactjsasynchronousloading

React loader component increases page loading time rather than showing itself when the page is loading


I have a page that is making a few heavy API calls when loading, it takes around 5-7 seconds to collect all the data. I referenced [this question] and decided to add a loader with setTimeout to simulate additional "API calls" and timed loading time with and without the loader.

Without the loader it took - 6.92 secs

With the loader it took - 14.05 secs

This is my code:

    const [loading, setLoading] = useState(false);

    useEffect(() => {
        async function updateUI() {
            const ethers_owner = await administrativeSidechainContract.owner()
            setContractOwner(() => {
                return {contractOwner: ethers_owner.toLowerCase()}})

            const ethers_matchCountMessage = await administrativeSidechainContract.matchCount()
            setMatchCount(() => {
                return {matchCount: ethers_matchCountMessage,}})
        }
        updateUI()
        //here is the loader simulation
        setLoading(true);
        setTimeout(() => {
            setLoading(false);
        }, 7000);

    }, [])

    return (
        <>
            {loading ?
                <div className="loader-container"></div> :
                <div className="decks-container"></div>}
        </>
    )

From my testing it seems that the loader just increases the page loading time by whichever amount of setTimeout that I set.

How do make I make data loading time and setTimeout times overlap rather than go on top of each other?

Thanks for your time in advance!


Solution

  • I think you don't need setTimeout for this. Instead, you can do something like this:

    • Set the loader state to true before updateUI is called
    • Set the loader state to false, when you feel that your task is done

    Following is an example:

    useEffect(() => {
        const res = [];
        async function updateUI() {
            await Promise.all([
                administrativeSidechainContract.owner(),
                administrativeSidechainContract.matchCount()
            ])
            .then(results => {
              res.push(results)
            });
            const ethers_owner = res[0];
            const ethers_matchCountMessage = res[1];
            // you may set loader to false here
            setLoading(false);
            setContractOwner(() => {
                return {contractOwner: ethers_owner.toLowerCase()}})
             
            setMatchCount(() => {
                return {matchCount: ethers_matchCountMessage,}})
        }
    
        setLoading(true);
        await updateUI();
        // If you don't want to setLoading(false) inside updateUI method, you may set loader to false here
    }, [])