Reboot
Reboot

Reputation: 3

Async request in useEffect doesn't work like async

I'm trying to take data from a backend,it takes data , but it doesn't display data on the page until the component calls componentDidUpdate() , but with the second function it works. I think that the it mounting component before the taking data , i tried to use 'uselayouteffect' but it didn't solve the problem , by using console.log , i understood that the problem in the my async functions , but the functions are the same (i mean structure) .

useEffect:

useEffect( () => {

    console.log('ProfileUseEffect')

    getUserInfo().then( (response) => {
        console.log(response)
    }).catch((error) => {
        console.log(error)
    })


    loadAllSessions().then( (response) => {
        console.log(response)
    }).catch((error) => {
        console.log(error)
    })

}, [])

function that doesn't work correctly :

    const getUserInfo = async () => {

    console.log('ThisShitGonnaWork')

    const requestData = {
        "client": requestClient,
        "key": requestKey,
        "data":{
            "action":"getInfo",
            "token": accessTokenCookie['access_token'],
        }
    }

    try{
        const response = await axios.post(
            backendUrl + 'user' , requestData
        )

        setUserAccountInfo(response?.data?.message)

        typeof  userAccountInfo.userlogin !== 'undefined' &&  setUserLogin(userAccountInfo.userlogin)
        typeof  userAccountInfo.username !== 'undefined' &&  setUserName(userAccountInfo.username)
        typeof  userAccountInfo.userrole !== 'undefined' &&  setUserRole(userAccountInfo.userrole)

    }catch (err){
        console.log(err)
    }
    
}

function that works correctly:

    const loadAllSessions = async () => {
    
    const requestData = {
        "client": requestClient,
        "key": requestKey,
        "data":{
            "action":"getActiveSessions",
            "token": accessTokenCookie['access_token'],
        }
    }

    try{
        const response = await axios.post(
            backendUrl + 'user', requestData
        )
        response?.data?.message?.activeSessions.forEach( (elem , idx ) => {
            updateUserSessionsMap(idx , elem)
        })

    }catch (err){
        console.log(err)
    }


}

Upvotes: 0

Views: 59

Answers (1)

Milos Pavlovic
Milos Pavlovic

Reputation: 1450

It does not work because of this part:

 try{
        const response = await axios.post(
            backendUrl + 'user' , requestData
        )

        setUserAccountInfo(response?.data?.message)

        typeof  userAccountInfo.userlogin !== 'undefined' &&  setUserLogin(userAccountInfo.userlogin)
        typeof  userAccountInfo.username !== 'undefined' &&  setUserName(userAccountInfo.username)
        typeof  userAccountInfo.userrole !== 'undefined' &&  setUserRole(userAccountInfo.userrole)

    }catch (err){
        console.log(err)
    }

You are doing setUserAccountInfo and then you are expecting in next line that you will access that new state by inspecting typeof userAccountInfo..., and you will not, because state update is async and you will access new state only after rerender(in next function call) - state is being accessed from closure which recreates on each rerender.

Rewrite to this:

try{
        const response = await axios.post(
            backendUrl + 'user' , requestData
        )
        
        const accountInfo = response?.data?.message;
        setUserAccountInfo(accountInfo)
        

        typeof  accountInfo.userlogin !== 'undefined' && setUserLogin(accountInfo.userlogin)
        typeof  accountInfo.username !== 'undefined' &&  setUserName(accountInfo.username)
        typeof  accountInfo.userrole !== 'undefined' &&  setUserRole(accountInfo.userrole)

    }catch (err){
        console.log(err)
    }

You need to preserve value you are passing into setUserAccountInfo and then use that value(and not the current state) to do some additional checks and state updates.

Upvotes: 1

Related Questions