Home > Blockchain >  React useState and Firebase onSnapshot
React useState and Firebase onSnapshot

Time:12-04

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.

  • Related