1

I'm trying to implement a chat app with infinite scroll using Firebase. The problem is that if I don't empty my messages array when a new message is added then they're duplicated. If I empty the messages array then it doesn't keep the previous messages.

Here is the code:

  getAllMessages(matchId: string) {
    this.chatSvc.getAllMessages(matchId)
      .orderBy('createdAt', 'asc')
      .limitToLast(5)
      .onSnapshot((doc) => {
        if (!doc.empty) {
          this.messages = [];
          doc.forEach((snap) => {
            this.messages.push({
              content: snap.data().content,
              createdAt: snap.data().createdAt,
              sendingUserId: snap.data().sendingUserId,
              receivingUserId: snap.data().receivingUserId
            });
          });
        } else {
          this.messages = [];
        }
      });
  }
And the chat service that returns the reference:

  getAllMessages(matchId: string): firebase.firestore.CollectionReference<firebase.firestore.DocumentData> {
    return firebase
    .firestore()
    .collection(`matches`)
    .doc(`${matchId}`)
    .collection('messages');

  }

I'm pushing the messages from the collection in to a messages array. If I don't add 'this.messages = []' then it will duplicate messages every time a new one is added to the collection.

How do I only get the new document from firebase with onSnapshot instead of it iterating through all of the collection again? I only want the last message because I'm going to implement infinite scroll with another query that retrieves previous messages.

Any help would be greatly appreciated.

D.Hodges
  • 1,794
  • 4
  • 24
  • 47

1 Answers1

2

the query will always return the last 5 result whenever a new entry that matches the condition occurs, which will create the duplicates. What you can do is to listen to changes between snapshots

getAllMessages(matchId: string) {
    this.chatSvc.getAllMessages(matchId)
      .orderBy('createdAt', 'asc')
      .limitToLast(5)
      .onSnapshot((snapshot) => {
        snapshot.docChanges().forEach((change) => {
          // push only new documents that were added
          if(change.type === 'added'){
           this.messages.push(change.doc.data());
          }
        });
      });
  }