I am currently in the process of developing a chat application. During the initialization of the chat page, I am checking for messages and storing them in an array.
ngOnInit() {
this.messageService.getMessages().doc(`${this.sortItineraries[0] + '-' + this.sortItineraries[1]}`)
.onSnapshot((doc) => {
console.log('Initializing message.page in snapshot', doc.data().message);
this.messages = [];
this.messages = doc.data();
console.log('Initializing message.page variable', this.messages);
});
}
The issue of an infinite loop arises when sending a message using the following code
getMessages() {
return this.allMessages;
}
getAllMessages() {
return this.allMessages;
}
async createMessage(itineraries) {
console.log('Creating Message');
const docRef = await firebase.firestore().doc(`messages/${itineraries}`).set({
message: []
});
}
async sendMessage(id, content, userId) {
this.allMessages.doc(`${id}`)
.onSnapshot((doc) => {
if (doc.exists) {
console.log('sendMessage doc exists');
this.send(id, content, userId);
} else {
this.createMessage(id)
.then(() => {
console.log('sendMessage !doc exists');
this.send(id, content, userId);
});
}
});
}
async send(id, content, userId) {
console.log('send');
const uid = this.loggedInUser.uid;
const ref = this.afs.collection('messages').doc(id);
return ref.update({
message: firebase.firestore.FieldValue.arrayUnion({
content,
createdAt: Date.now(),
userId
})
});
}
<ion-content>
<ion-list lines="none">
<ion-item *ngFor="let message of messages.message">
<div size="9" *ngIf="myItinerary.userId !== message.userId" class="message other-user">
<span>{{message.content}}</span>
<div class="time" text-right><br>
{{message.createdAt | date: 'short'}}</div>
</div>
<div offset="3" size="9" *ngIf="myItinerary.userId === message.userId" class="message me" slot="end">
<span>{{message.content}}</span>
<div class="time" text-right><br>
{{message.createdAt | date: 'short'}}</div>
</div>
</ion-item>
</ion-list>
</ion-content>
<ion-footer>
<ion-toolbar light="light">
<ion-row align-items-center no-padding>
<ion-col size="8">
<textarea autosize maxRows="3" [(ngModel)]="newMsg" class="message-input"></textarea>
</ion-col>
<ion-col size="3">
<ion-button expand="block" fill="clear" color="primary" [disabled]="newMsg === ''" class="msg-btn"
(click)="sendMessage()">
<ion-icon name="ios-send" slot="icon-only"></ion-icon>
</ion-button>
</ion-col>
</ion-row>
</ion-toolbar>
</ion-footer>
https://i.stack.imgur.com/2zIw0.png
The screenshot highlights the console logs that keep looping between the service responsible for creating and sending messages to the Firebase backend and the initialization process. This loop continues until exiting the app and deleting the messages in Firebase.
In the service, I first check if the document is created before proceeding with pushing the messages into the array stored in Firebase
async sendMessage(id, content, userId) {
this.allMessages.doc(`${id}`)
.onSnapshot((doc) => {
if (doc.exists) {
console.log('sendMessage doc exists');
this.send(id, content, userId);
} else {
this.createMessage(id)
.then(() => {
console.log('sendMessage !doc exists');
this.send(id, content, userId);
});
}
});
}
If the document does not exist, I create it before adding the messages to the array in Firebase
<ion-list lines="none">
<ion-item *ngFor="let message of messages.message">