Eli Levit
Eli Levit

Reputation: 67

How to setState only when "map" loop is finished?

I send some http requests and after the Promises have solved I need to loop through the array and to do some async things. I want to leave the function asynchronous but I need to execute setState only after "map" loop is finished:

fetchData = () => {
 let data = [];
 let tickets  = http.get('/api/zendesk/tickets'),
     users    = http.get('/api/zendesk/users'),
     items    = http.get('/api/orders/items'),
     reqTypes = http.get("/api/support/requests");

 Promise.all([users,tickets,items,reqTypes])
  .then(values => {
    console.log(values);
    let usersArr = values[0].data.users,
      ticketsArr = values[1].data.tickets,
        itemsArr = values[2].data,
      requestArr = values[3].data;

    data = ticketsArr.map((ticket,key) => {

      let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;

      id === null ? ticket.Items = [] : ticket.Items = itemsArr.filter(item => item.order_id === parseInt(id));

      ticket.Requests = requestArr.filter(request => request.id === ticket.id);
    })

    this.setState({tickets:data})

  }).catch(err => console.log(err))
 }

Is it possible to do or I need to make sync loop like "for"? Here is the screen:

Upvotes: 2

Views: 1595

Answers (2)

Mayank Shukla
Mayank Shukla

Reputation: 104379

I get an array of "undefined objects", Why?

Because you are not returning anything inside map body, and by default it returns undefined.

Check this snippet:

let a = [1,2,3,4].map(el => {
   console.log('el = ', el);
})

console.log('a = ', a);   //array of undefined values

If you wants to modify the existing array, then use forEach instead of map.

Like this:

ticketsArr.forEach((ticket,key) => {
    let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;
    ticket.Items = (id === null) ? [] : itemsArr.filter(item => item.order_id === parseInt(id));
    ticket.Requests = requestArr.filter(request => request.id === ticket.id);
})

this.setState({ tickets: ticketsArr })

Upvotes: 1

casraf
casraf

Reputation: 21694

Array.prototype.map expects you to return how each element should be in its final form. Right now you are not returning anything, hence every element becoming undefined.

data = ticketsArr.map((ticket,key) => {
  let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;
  id === null ? ticket.Items = [] : ticket.Items = itemsArr.filter(item => item.order_id === parseInt(id));
  ticket.Requests = requestArr.filter(request => request.id === ticket.id);
  return ticket // <- this
})

Upvotes: 1

Related Questions