0

I have a React hook with this structure. What I want to do is, after finish calling getUserJoinedSlotList() and getting the result, then I want to call getAllAvailableSlot() both set the result into the useState hooks.

const [joinedSlotList, setJoinedSlotList] = useState(null)
const [availableSlotList, setAvailableSlotList] = useState(null)
const [isAllSlotLoading, setIsAllSlotLoading] = useState(true)

const getJoinedList = () => {
        getUserJoinedSlotList()
            .then(res => {
                setIsLoading(false)
                setJoinedSlotList(res.joined_slot)
            })
            .catch(error => {
                setIsLoading(false)
                setErrorMsg(error.message)

            })
    }


const getAvailableSlotList = () => {
        getAllAvailableSlot()
            .then(res => {
                setIsAllSlotLoading(false)  // this setting not working, at the 2nd API call
                setAllAvailableSlotList(res.slot)
            })
            .catch(error => {
                setAvailableErrMsg(error.message)
                setIsAllSlotLoading(false)
            })
    }

useEffect(() => {
        if (user !== null) {
            getJoinedList()
         }
    }, [user])

Here is the code for getAvailableSlot(), I am using Aws amplify, so it actually return a promise for the GET request

import { API } from 'aws-amplify';

export const getAllAvailableSlot = async () => {
    let path2 = path + '/list_all'

    return API.get(apiName, path2)
}

What I tried:

Put in getAvailableSlotList as a callback function of getJoinedList(), like this:

const getJoinedList = (callback) => {
        getUserJoinedSlotList()
            .then(res => {
                setIsLoading(false)
                setJoinedSlotList(res.joined_slot)
            })
            .catch(error => {
                setIsLoading(false)
                setErrorMsg(error.message)

            })

        callback()
    }

then
useEffect(() => {
        if (user !== null) {
            getJoinedList(getAvailableSlotList) // put in as call back here
         }
    }, [user])

By this, getAllAvailableSlot is called, I getting the result. But the result is not being set after calling setAvailableSlotList, and setIsAllSlotLoading(false) is not working as well, still true

Then I tried to call like this:

const getJoinedList = () => {
        getUserJoinedSlotList()
            .then(res => {
                setIsLoading(false)
                setJoinedSlotList(res.joined_slot)

               

                getAvailableSlotList() // here call the function 
            })
            .catch(error => {
                setIsLoading(false)
                setErrorMsg(error.message)

            })
    }

Again, is same result as above attempt.

Then I tried like this as well:

const calling = async () => {
        await getJoinedList()
        await getAvailableSlotList() //setAvailableSlotList and setAllIsLoading is not working, the 2ND CALL
    }

useEffect(() => {
        if (user !== null) {
            
                //getJoinedList()
                calling()
            
        }
    }, [user])

But still the getAvailableSlotList() set hooks is not taking any effect.

Specific problem:

I noticed that, the 2nd API calling is successful, but the follow up function which I call to setting the hooks, it just not taking any effect.

Means that: Everything in getJoinedList() is working just fine. But when reach to getAvailableSlotList(), I can get the API result from it, but the setAvailableSlotList and setIsAllSlotLoading both cant set in the value

Question:

  1. How to call another API after 1 API call is finished?

  2. How to set react hooks at the 2nd API call?

ken
  • 2,426
  • 5
  • 43
  • 98
  • can you share the code for `getAllAvailableSlot()`? The second attempt looks right to me. My guess is it's never reached the `.then` block. – Claire Lin Jun 18 '21 at 21:01
  • @ClaireLin sure, wait a moment – ken Jun 18 '21 at 21:02
  • @ClaireLin I actually using Aws amplify, so i just return a promise from the Get request. I just updated the question, pulling my hair off.. haha – ken Jun 18 '21 at 21:06
  • 1
    The second approach you tried should be working: https://codesandbox.io/s/romantic-bhaskara-odw6i?file=/src/App.js – Claire Lin Jun 18 '21 at 21:17
  • @ClaireLin is exactly the same from what you provide. It just cant set the hooks in the `callSecond()`, I just dont know why – ken Jun 18 '21 at 21:43
  • Does this answer your question? [How to resolve promises one after another?](https://stackoverflow.com/questions/33251935/how-to-resolve-promises-one-after-another) – Heretic Monkey Jun 18 '21 at 21:49
  • @ClaireLin miss ur answer helped me, it works, thank you for ur help – ken Jun 18 '21 at 22:22
  • 1
    @ken Wrote up as a proper answer with a bit more explanation on why the first/thrid attempts didn't work. Hope it helps! – Claire Lin Jun 19 '21 at 08:14

3 Answers3

1

Your second attempt should work. Here is a simplified sandbox example: https://codesandbox.io/s/romantic-bhaskara-odw6i?file=/src/App.js

A bit explanation on where the first and third attempts went wrong:

The first attempt is almost there, just that you need to move callback() inside the .then() block which essentially brings you to the second attempt.

The third one you used async/await but the problem is neither getJoinedList() nor getAvailableSlotList() returns a Promise so both requests will be sent around the same time without one waiting on the other to resolve first.

Claire Lin
  • 2,372
  • 8
  • 13
0

The simplest solution is actually to add your entire getAllAvailableSlot() function inside the getUserJoinedSlotList() through chaining. I see you're already using that, so I don't need to explain it in depth.

getUserJoinedSlotList().then(res => {
    --- logic ---
    getAllAvailableSlot().then(res2 => {
       -- logic ---
    }
}
Maxwell
  • 405
  • 3
  • 8
0

Then chaining and its pairing could work here.

await getUserJoinedSlotList()
    .then(res => /*assign hooks data*/)
    .then(() => getAllAvailableSlot())
    .then(availableSlot => /*assign availableSlot data*/)
    .catch(e => console.log(e))
bhaginath
  • 456
  • 4
  • 13