Home > Blockchain >  Preventing a setState from running until network request is complete
Preventing a setState from running until network request is complete

Time:11-28

I have the following function, inside of a Context file in my React app:

const fetchAll = (userId) => {

        try {
            fetchDetails(userId)
            // To be clear... There's multiple functions here, i.e:
            // fetchContact(userId)

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

        setPending(false)

    }

I've removed some of the functions - but the main premise of the function is to combine multiple promises together, and until these are complete, display a 'pending' component.

This pending component is displayed if the 'pending' state is set to true:

const [pending, setPending] = useState(true)

However, at the moment, what is happening is that the try is attempted, but the setPending is executed at the same time.

I thought one way around this would be to utilise a 'finally' call at the end of the my try / catch, but that still executes at the same time. Like this:

const fetchAll = (userId) => {

        try {
            fetchDetails(userId)
        } catch (err) {
            console.log(err)
        } finally {
            setPending(false)
        }

    }

I don't want any of my functions to be run asynchronously: I want them all to execute at the same time to prevent a waterfall effect of multiple network requests at once.

For reference, my individual 'fetch' functions call an endpoint and set state data based upon the response:

const fetchDetails = (userId) => {
        axios.post("/api/fetch/fetchDetails", {
            id: userId
        })
        .then((response) => {
            console.log(response.data)
            setName(response.data.name)
            setPreviewPhoto(response.data.profile_picture_url)
            setPhotoName(response.data.profile_picture_name)
            setPhotoFile(response.data.profile_picture_url)
        })
    }

Does anyone have any suggestions as to how I could make this work?

CodePudding user response:

fetchDetails returning a promise, you need to use async/await

const fetchAll = async (userId) => {

    try {
        await fetchDetails(userId)
    } catch (err) {
        console.log(err)
    } finally {
        setPending(false)
    }

}

CodePudding user response:

You can have multiple async calls using Promise.all() or Promise.allSettled() depending on your use case.

setPending(true)
try {
  await Promise.all([() => fetchAll(1), () => fetchAll(2)])
} finally {
  setPending(false)
}

This will wait for all calls to complete (or one to fail)

CodePudding user response:

Let's assume you have 2 API calls: fetchAll('123') and fetchAll('321');

In order to wait for all of your requests and then update your state, you should use Promise.all like this:

Promise.all([fetchAll('123'), fetchAll('321')]).then((responses) => {
  setPending(false)
}
  • Related