Home > other >  Firestore query onSnapshot is returning me all previous docs on each change
Firestore query onSnapshot is returning me all previous docs on each change

Time:12-29

I am adding docs to a collection of messages. For getting real time updates in my UI, I am listening to new docs that have been created after "new Date()".

The thing is that, after getting the first snapshot with all the documents that match the query, when a new doc is added, I am receiving all the previous detected docs in the listener.

Is this the expected behavior?? What am I doing wrong?

This is what I am doing:

    export function listenNonDeletedChatMessages(
      chatRoomId,
      startAt = undefined,
      onMessageReceived = undefined,
      onNext = undefined,
      one rror = undefined
    ) {
      const currentUser = getCurrentUser();
    
      if (!currentUser) {
        throw authErrors.authenticationRequired();
      }
    
      let query = firestore
        .collection("chats")
        .doc(chatRoomId)
        .collection("messages")
        .where("content.deletedAt", "==", null)
        .orderBy("date");
    
      if (startAt) {
        query = query.startAt(startAt);
      }
    
      return query.onSnapshot(handleChanges, one rror);
    
      function handleChanges(querySnapshot) {
        const messages = [];
    
        querySnapshot.docs.forEach((doc) => { // I am getting N docs on each change, why? 
          const messageData = {
            id: doc.id,
            ...doc.data(),
          };
    
          const parsedMessage = parseChatMessage(
            messageData,
            currentUser.uid
          );
    
          console.log(messageData); <--- this method is logging me all the already detected docs!
    
          messages.unshift(parsedMessage);
    
          onMessageReceived?.(parsedMessage);
        });
    
        querySnapshot.docChanges().forEach((change) => { // 1 change detected, as expected
          console.log(change.type); <--- THIS ONLY LOGS "added" one time when a doc is added!
        });
    
        onNext?.(messages);
      }
    }

Note: I am not talking about the initial status, where all docs are fetched, I am saying that I am receving the same docs again and again on any new doc addition, while they are not being modified.

CodePudding user response:

That is the expected behavior: the QuerySnapshot contains information about all documents that match the query, not just about the changes.

If you want to process all documents, loop over docs as you do first in your code.

If you want to process only the changes, loop over docChanges as you do later in your code.

CodePudding user response:

Based on Frank Solution, in order to avoid getting same docs of the query, doing something like this will work:

export function listenNonDeletedChatMessages(
  chatRoomId,
  startAt = undefined,
  onMessageReceived = undefined,
  onNext = undefined,
  one rror = undefined
) {
  const currentUser = getCurrentUser();

  if (!currentUser) {
    throw authErrors.authenticationRequired();
  }

  let query = firestore
    .collection("chats")
    .doc(chatRoomId)
    .collection("messages")
    .where("content.deletedAt", "==", null)
    .orderBy("date");

  if (startAt) {
    query = query.startAt(startAt);
  }

  return query.onSnapshot(handleChanges, one rror);

  function handleChanges(querySnapshot) {
    const messages = [];

    querySnapshot.docChanges().forEach((change) => {
      if (change.type === "added") {
        const messageData = {
          id: change.doc.id,
          ...change.doc.data(),
        };

        const parsedMessage = parseChatMessage(
          messageData,
          currentUser.uid
        );

        messages.unshift(parsedMessage);

        onMessageReceived?.(parsedMessage);
      };
    });

    onNext?.(messages);
  }
}
  • Related