I want to automatically fetch new incoming messages from a firestore collection using onSnapshot. While I can set the state inside the callback, I cannot read it.
const [messages, setMessages] = useState(null);
const [chat, setChat] = useState(props.chatId);
useEffect(() => {
const q = query(collection(db, "messages"), where("chat_id", "==", chat), orderBy("date","desc"), limit(5));
// Create the DB listener
const unsuscribe = onSnapshot(q, (querySnapshot) => {
console.log(messages);
if(messages === null){
console.log("setting messages the first time");
setMessages(querySnapshot.docs)
}else{
console.log("updating messages");
setMessages([...querySnapshot.docs, ...messages])
}
});
return () => {
console.log("unsubscribe");
unsuscribe();
}
}, [chat]);
Whenever onSnapshot
fires, messages
is always null
but setMessages
works since the messages are displayed. I tried so many approaches but I could not get it to work.
Help much appreciated.
CodePudding user response:
did you try this from the documentation
const q = query(collection(db, "cities"), where("state", "==", "CA"));
const unsubscribe = onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach((change) => {
if (change.type === "added") {
console.log("New city: ", change.doc.data());
}
if (change.type === "modified") {
console.log("Modified city: ", change.doc.data());
}
if (change.type === "removed") {
console.log("Removed city: ", change.doc.data());
}
});
});
Also the question is a bit confusing on what you want to achieve
CodePudding user response:
The querySnapshot
you get from Firestore always contains all snapshots that match the query, not just the changed/new documents.
So your onSnapshot
handler can be much simpler:
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setMessages(querySnapshot.docs)
});
So: every time you get notified by Firestore that the data in q
has changed, you pass the data on to the state/UI for rendering.