How i can avoid the loop on my querysnapshot.foreach?

My User has 2 teams :

  • Danse
  • Judo

On my subcollection "membersList" the team Danse had 1 friend request and Judo had none.

So I’m suppose to have just one request on my screen. But when I have 2 or more teams, the while continue to loop and the request appear with the numbers of team.

I think the problem is on my querySnaphost.forEach but on my console he return me the doc not empty (so the team danse ) and an other one with document not found.

let fetch = async () => {
    firestore()
      .collection("Teams")
      .where("uid", "==", await AsyncStorage.getItem("userID"))
      .get()
      .then((querySnapshot) => {
        if (querySnapshot.empty) {
          console.log("no documents found");
        } else {
          querySnapshot.forEach((doc) => {
            let Teams = doc._data;
            console.log(Teams);
            updateActivity((arr) => [...arr, Teams]);
            console.log(Activity);

            doc.ref
              .collection("membersList")
              .where("statut", "==", "en attente")
              .get()
              .then((querySnapshot) => {
                if (querySnapshot.empty) {
                  console.log("no documents found cc");
                } else {
                  querySnapshot.forEach((doc) => {
                    let members = doc._data;
                    console.log("aa", members);
                    updateMembersList((arr) => [...arr, members]);
                    console.log("cc", MembersList);
                  });
                }
              });
          });
        }
      });
  };
  useEffect(() => {
    fetch();
  }, []);

Here is what is logged when fetch() is called:

{"Activity": "Danse", "Adress": "Plage", "City": "Nice", "Owner": true, "members": "3", "text": "bouh", "tokenTeam": "n5ounxsf2bq", "uid": "PTbEn2fba0QudXI8JE8RioQ9of53"}
[]
no documents found cc

Answer

You should not name your function fetch as this is a reserved global function which you should treat like undefined – don’t assign anything to it. I recommend also using const over let where applicable.

Note: This answer makes use of the same strategy described in this answer.

const fetchMemberRequests = async () => {
  const userTeamsQuerySnapshot = await firestore()
    .collection("Teams")
    .where("uid", "==", await AsyncStorage.getItem("userID"))
    .get();

  if (userTeamsQuerySnapshot.empty) {
    console.log("User owns no teams.");

    // empty Activity & MembersLists
    updateActivity([]);
    updateMembersList([]);
    return;
  }
  
  // for each team, fetch the pending requests and return a { team, memberRequests } object
  const fetchMemberRequestsPromises = userTeamsQuerySnapshot.docs
    .map(async (teamDocSnapshot) => {
      const teamData = teamDocSnapshot.data();
      
      const memberRequestsQuerySnapshot = await teamDocSnapshot.ref
        .collection("membersList")
        .where("statut", "==", "en attente")
        .get();
        
      if (memberRequestsQuerySnapshot.empty) {
        console.log(`Activity ${teamData.Activity} has no pending requests.`);
        return {
          team: teamData,
          memberRequests: []
        }
      }
      
      const memberRequestsArray = memberRequestsQuerySnapshot.docs
        .map((memberRequestDocSnapshot) => memberRequestDocSnapshot.data());
        
      console.log(`Activity ${teamData.Activity} has ${memberRequestsArray.length} pending requests.`);
      return {
        team: teamData,
        memberRequests: memberRequestsArray
      }
    });
    
  const memberRequests = await Promise.all(fetchMemberRequestsPromises);
  
  // memberRequests is an array of { team: teamData, memberRequests: arrayOfMembers }
  // which could be used to show the requests in groups
  
  // these lines replicate your current code:
  const allTeams = [];
  const allMemberRequests = [];
  for (const request of memberRequests) {
    allTeams.push(request.team);
    allMemberRequests.push(...request.memberRequests); // note: spreads array
  }
  
  console.log(`User owns ${allTeams.length} teams, with a total of ${allMemberRequests.length} pending requests.`);
  
  // replace Activity and MembersList rather than append to them
  updateActivity(allTeams);
  updateMembersList(allMemberRequests);
}