How to fix this array copying problem in React?

I created an array using some data then I tried to copy it to the useState array. But it doesn’t work. Also, I viewed it using the console log. but line 49 logged before line 36. can I fix this?

Console -

Code -

 const retrieveCompany = async () =>{
    try{
        
        const colletionRef = collection(db, 'corporations');
        const q = query(colletionRef, orderBy('createdAt', "desc"));

        const unsub =  onSnapshot ( q,(snapshot) => {
           setCorporations([]); 
           let list = [];
            snapshot.docs.forEach( async (doc) => {
              
              let newItem = {id: doc.id, ...doc.data()};
              if(newItem.poc) {
                  let userData = await getDoc(newItem.poc);
                  console.log(userData.data())

                  newItem = {pocUser: userData.data(), ...newItem}
                  console.log(newItem);
                  list.push(newItem);
                }
                else{
                  list.push(newItem);
                }

              // await getPOSUser(doc.data().poc);
              // list.push({ id: doc.id, ...doc.data()});
            })
          console.log(list)
          setCorporations(list); 
          console.log(corporations) 
        });
        return () => {
          unsub();
        }
    }catch(err){
      console.log(err);
    }
  }

You’re using an async callback inside the forEach(), but forEach() itself is not asynchronous. So the list will always be empty on line 50.

You probably want to use a combination of Promise.all() and map().

Let me know if you would like to see an example.

1 Like

@colinthornton please Can you give an example?

Let’s say you have a list of IDs ids.
Let’s say you have an asynchronous function fetchDocument that takes a single ID, and returns a promise that evaluates to some data.
Let’s say you want to fetch the document for every ID in the list and then log the entire list of documents.
That could look like this:

const ids = [1, 2, 3, 4, 5];
const docs = await Promise.all(
  ids.map(async (id) => {
    const doc = await fetchDocument(id);
    return doc;
  })
);
console.log(docs);
1 Like

I feel I should point out that there is one big difference to these two approaches though. With Promise.all() the fetches will be run at the same time in parallel. With await inside a for loop it will run sequentially, waiting for the first fetch to finish before starting the second, waiting for that to finish before moving onto the third, and so on. In theory, the parallel processing with Promise.all() should run faster so I would prefer it when parallelization is possible.

And sometimes you need sequential processing in which case Promise.all() is out, so @ravinduonline take notes, you’ll probably end up using both of these methods in your career.

(getting sidetracked here but…) Also, this is a pretty new API but they recently added Promise.allSettled() which works similarly but waits for all promises to finish, whether they succeed or fail. Haven’t got a chance to use it yet though.

2 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.