Reputation: 53
I am currently coding a chatting app with React Native and Expo, but at the point at receiving the messages in RealTime (If Message gets updated, delted or edited), but it doesn't do it in realtime, it fetches the data if i open the page for the chat, but after that it doesn't update anymore
Receiving messages:
const [Messages, setMessages] = useState([]);
var TmpMessages = [];
useEffect(() => {
const messages = () => {
firebase.firestore().collection('Users').doc(`${user.uid}`).collection('Friends')
.doc(`${data.Friend.FriendId}`).collection('Messages').orderBy('Index').onSnapshot(ss => {
var changes = ss.docChanges();
// Parsing the messages
for (var i = 0; i < changes.length; i++) {
const message = changes[i].doc.data();
if (changes[i].type == 'added') {
if (i == 0) message.BeforeAt = 'first message';
if (message.Sender == user.uid) {
if (i > 0) {
var beforeMessage = changes[i - 1].doc.data();
message.BeforeAt = beforeMessage.SendAt;
if (beforeMessage.Sender == user.uid) {
message.Type = 'SenderBottom';
} else {
message.Type = 'Sender';
}
} else {
message.Type = 'Sender';
}
} else {
if (i > 0) {
var beforeMessage = changes[i - 1].doc.data();
message.BeforeAt = beforeMessage.SendAt;
if (beforeMessage.Sender == data.Friend.FriendId) {
message.Type = 'ReceiverBottom';
} else {
message.Type = 'Receiver';
}
} else {
message.Type = 'Receiver';
}
}
TmpMessages.push(message);
} else if (changes[i].type == 'removed') {
for (var k = 0; k < TmpMessages.length; k++) {
if (TmpMessages[k].Id == message.Id) {
console.log(message.Id + ' got deleted')
TmpMessages.splice(k, 1);
}
}
} else if (changes[i].type == 'updated') {
for (var k = 0; k < TmpMessages.length; k++) {
if (TmpMessages[k].Id == message.Id) {
console.log(message.Id + ' got updated')
TmpMessages[k].Message = message.Message;
}
}
}
}
setMessages(TmpMessages);
});
}
// Unsubscribe from events when no longer in use
return () => messages();
}, []);
And this is my FlatList:
<FlatList
style={{ marginBottom: 60, }}
renderItem={({ item }) => {
return (
<ChatItem MessageData={{
content: item.Message,
beforeSendAt: item.BeforeAt,
sendAt: item.SendAt,
}} MsgType={item.Type} />
);
}}
data={Messages}
extraData={Messages}
keyExtractor={(item, index) => index.toString()}
/>
Edit: If I don't put my Firebase event listener in an useEffect, then it does an infinite loop an eventually crashes.
Edit 2: Don't blame me for my unifficient code for parsing the messages, right now it is only prove of concept
Upvotes: 0
Views: 156
Reputation: 7388
I would recommend to use the whole result each time something changes. Like here:
db.collection("cities").where("state", "==", "CA")
.onSnapshot((querySnapshot) => {
var cities = [];
querySnapshot.forEach((doc) => {
cities.push(doc.data().name);
});
console.log("Current cities in CA: ", cities.join(", "));
});
instead of ss.docChanges()
. Just loop over all messages. You add them anyway as a whiole to the state with setMessages(TmpMessages);
. That way you don't need to bother with all the changes. With .data()
you just get all of them if anything changes.
Upvotes: 1