Reputation: 41
I am making a chat with Ionic and react using firestore as my database. I am storing all the messages in an array []
in a document in firestore. And simply want both users to fetch the data again if a message is added. So i basically want to add a listener to my document. My chat is working but you have to reload the page to see new messages... This is my code:
const [chats, setChats] = useState([]);
db.collection("chats").doc(chatId).onSnapshot((doc) => {
setChats(doc.data().messages)
});
I either i get infinite loops or doc.data() is not defined. Is there a good way to fetch data using this function? Or do you need for example firebase cloud functions?
Upvotes: 1
Views: 4004
Reputation: 41
I solved my problem this way:
const [chats, setChats] = useState([]);
useEffect(() => {
db.collection("chats").doc(chatId).onSnapshot(snapshot => {
updateMessages(snapshot.data())
})
}, []);
function updateMessages(data : any) {
setChats(data.messages);
}
When i put the listener inside a useEffect()
hook i solved the problem with infinite loops since a new listener would start each time the state was updated inside the listener. Now the listener is only initialized once when the component is mounted.
And by sending snapshot.data()
to a function and THEN fetching data.messages
i solved the problem with snapshot.data().messages
being undefined.
Upvotes: 2
Reputation: 5819
Actually, the piece of code that you shared from the documentation builds a listener to changes on your database, so you don't need any infinite loops.
Quoting this documentation for realtime updates.
An initial call using the callback you provide creates a document snapshot immediately with the current contents of the single document. Then, each time the contents change, another call updates the document snapshot.
So everytime a new message is sent, onSnapshot
will be triggered. You can reference snapshot
instead of doc
on the callback that you provide and then you can use snapshot.docChanges()
to see what has changed. Here is an example:
db.collection("chats").doc(chatId)
.onSnapshot(function(snapshot) {
if(snapshot.docChanges().length > 0){
//do something
}
});
NOTE: If this is the first snapshot, all the data will be in the list as added changes and you can fetch the data by taking each change individually and referring to it's data: change.doc().data()
. Also, since you are querying by chatId
, the array should always have a size of 1.
Upvotes: 1