'React state resets when calling an async function

I'm trying to display a loader in react then execute an async function and then removing the loader but seems like the loader disappears as soon as the function starts executing.

Here's a sample code:

const component = () => {
    const [showLoader, setShowLoader] = useState(false)
    
    const clickHandler = async (status: string) => {
        setShowLoader(true)
        const success = await someAsyncFunction()
        success ? setShowLoader(false) : true
    }

    return (<div hidden={!showLoader}><Loader /></div>)
}

[Edit] Here is a simplified version of my someAsyncFunction:

const someAsyncFunction = async() => {
    for (let i=0;i < 99999;i++){
        console.log(i)
    }
    return Promise.Resolve(true)
}

It is evident that someAsyncFunction does return resolve the Promise and no sooner as it executes the loop for about 100K times



Solution 1:[1]

Given the nature of useState hook, it doesn't set the value instantly instead it's sort of a request queue. In this case, before the state is update, the function is called.

Best approach would be to use an useffect hook with the showLoader as it's dependency, and execute the function within it as it ensures the execution only after the state is set

Solution 2:[2]

inside the clickHandler funciton you are declaring a statement success ? setShowLoader(false) : true. the engine would reach this code after executing the someAsyncfunction. at this point the success is just a promise it has't fulfilled yet.the statement is true then the setShowloader will execute and set the loader to hide.a simple solution is to put await keyword befor success inside that statement.this is how we tell the engine that execute the statement whenever the success is fulfilled or rejcted.

 (await success) ? setShowLoader(false) : true

Solution 3:[3]

Hey from what I see there, Your the bang ! your using changes the state your using if it's true it will false and vice-versa

so I suggest you do this instead. if hidden is false the loading will be seen. if the functions is a success you turn hidden to true else it will keep showing Loader

const component = () => {
    const [showLoader, setShowLoader] = useState(false)
    
    const clickHandler = async (status: string) => {
        const success = await someAsyncFunction()
        success ? setShowLoader(true) : null
    }

    return (<div hidden={showLoader}><Loader /></div>)
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hmm
Solution 2 KeyvanKh
Solution 3