Shivam Sahil
Shivam Sahil

Reputation: 4921

ReactJS: How to return object asynchronously after fetching data in loop?

I have a react function as shown below:

const requestSideBarData = (state, request) => {

    let newState = state;
    Object.keys(newState.data).forEach(element => {
         axios.post(`${ApiEndPoints.getDropDownHeaders}${element}`,request)
        .then(response => {
            newState.data[element] = response.data;
        })
        .catch(e => {
            console.log(e);
            
        });
    });
    return newState;

};

I want to return the newState after all the post response has been recieved and newState has been updated. How should I go about it? Since the function runs syncly it returns the same state without letting axios complete its response.

Upvotes: 1

Views: 64

Answers (3)

Mohammed Imran
Mohammed Imran

Reputation: 77

You can do something like this.

const requestSideBarData = (state, request) => {
    let newState = state;
    try {    
        Object.keys(newState.data).forEach(async (element) => {
        const url =`${ApiEndPoints.getDropDownHeaders}${element}`;

        cosnt {data} = await axios.post(url,request);
        newState.data[element] = data;
        } catch(e) {
            console.log(e);
        }
    });
    return newState;
};

Upvotes: 1

wangdev87
wangdev87

Reputation: 8751

Use Promise.all

const requestSideBarData = async(state, request) => {

    let newState = state;
    const promises = [];
    Object.keys(newState.data).forEach(element => {
        promises.push(axios.post(`${ApiEndPoints.getDropDownHeaders}${element}`,request))
    });
    const results = await Promise.all(promises);
    var index = 0;
    Object.keys(newState.data).forEach(element => {
        newState.data[element] = results[index++].data;
    })
    return newState;

};

Upvotes: 2

Akash Sarode
Akash Sarode

Reputation: 447

try this,

const requestSideBarData = async (state, request) => {
  let newState = state;
  for(let element in Object.keys(newState.data)) {
    try {
      let response = await 
        axios.post(`${ApiEndPoints.getDropDownHeaders}${element}`,request);
      newState.data[element] = response.data;
    } catch(e) {
      console.log(e);
    }
  }
  return newState;
};

now that you've declared requestSideBarData body to be async, it will automatically return a promise, and you'll need to deal with it when calling the function.

I've also replaced forEach loop with for...in because forEach loop cannot run async by default. Now in every iteration loop will await the axios.post.

Ideally, you shouldnt await on every async function when you have a lot of them. see William Wang's answer to make all requests asynchronously and await on them all at once.

Upvotes: 1

Related Questions