Mel
Mel

Reputation: 695

How to get multiple references in a firestore snapshot

I have a firestore collection containing post documents, each document contains a reference to an author (user) and a case document.

How do I get the user and the case in the same onSnapshot?

Here's what I'd like to do with await, but that doesn't seem to be an option with react-native-firebase.

export const firebasePostLooper = (snapshot) => {
  let data = [];

  snapshot.forEach(async (doc) => {
    let newItem = {id: doc.id, ...doc.data()};
    if (newItem.author) {
      let authorData = await getDoc(newItem.author); // doesn't work with rnfirebase
      if (authorData.exists()) {
        newItem.userData = {userID: authorData.id, ...authorData.data()};
      }
    }
    if (newItem.case) {
      let caseData = await getDoc(newItem.case);
      if (caseData.exists()) {
        newItem.userData = {userID: caseData.id, ...caseData.data()};
      }
    }
    data.push(newItem);
  });
  return data;
};

This doesn't work because getDoc() doesn't exist.

So I'm left with using .then()


export const firebasePostLooper = (snapshot) => {
  let data = [];

  snapshot.forEach((doc) => {
    let newItem = {id: doc.id, ...doc.data()};

    if (newItem.author) {
      newItem.author
        .get()
        .then((res) => {
          newItem.authorData = res.data();
          if (newItem.case) {
            newItem.case
              .get()
              .then((caseRes) => {
                newItem.caseData = caseRes.data();
                data.push(newItem);
              })
              .catch((err) => console.error(err));
          }
        })
        .catch((err) => console.error(err));
    } else {
      data.push(newItem);
    }
  });
  return data;
};

This second method doesn't seem to be working, data is empty at the return statement but data.push(newItem) contains the correct document with the 2 referenced documents.

Upvotes: 1

Views: 498

Answers (1)

Christer Loob
Christer Loob

Reputation: 161

You're returning data before it gets filled inside the promise. You should handle the returning of the data inside a .then() in order to return it after the promise has resolved and not before.

Take a look at this example where if we handle the emptyData object outside the promise chain, we just return the initial value before it has been filled.

let promise = new Promise((resolve, reject)=>{
setTimeout(resolve, 1000, 'foo');
})

let emptyData= [];
let notEmptyData = [];

promise
.then(res=>{
    emptyData.push(res);
  notEmptyData.push(res);
    console.log("Full data: " + notEmptyData) // "Full data: foo"
});



console.log("Empty data: " + emptyData); // "Empty data: "

Upvotes: 1

Related Questions