【问题标题】:React useState and Firebase onSnapshot反应 useState 和 Firebase onSnapshot
【发布时间】:2022-01-09 20:31:26
【问题描述】:

我想使用 onSnapshot 从 Firestore 集合中自动获取新的传入消息。虽然我可以在回调中设置状态,但我无法读取它。

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]);

每当onSnapshot 触发时,messages 始终为null,但setMessages 在消息显示后有效。我尝试了很多方法,但我无法让它发挥作用。

非常感谢您的帮助。

【问题讨论】:

    标签: javascript reactjs firebase google-cloud-firestore react-hooks


    【解决方案1】:

    所以我设法找到了解决方案。诀窍是用useEffect()监听消息的状态变化

    const [snapShot, setSnapshot] = useState(null);
    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));
           
            const unsuscribe = onSnapshot(q, (querySnapshot) => {
                setSnapShot(querySnapshot)
            });
            return () => {
                unsuscribe();
            }
        }, [chat]);
    
    useEffect(() => {
      if(messages === null){
                    console.log("setting messages the first time");
                    setMessages(snapShot.docs)
                }else{
                    console.log("updating messages");
                    setMessages([...snapShot.docs, ...messages])
                }
        }, [snapShot]);
    

    【讨论】:

      【解决方案2】:

      你从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());
          }
        });
      });
      

      这个问题对你想要实现的目标有点困惑

      【讨论】:

      • 这就是我正在做的。问题是,在 onSnapshot 回调中,我无法读取消息的当前状态。我只是想监听集合中的变化并将它们添加到已经存在的集合中。
      【解决方案3】:

      您从 Firestore 获得的 querySnapshot 始终包含与查询匹配的所有快照,而不仅仅是更改/新文档。

      所以你的onSnapshot 处理程序可以简单得多:

      const unsubscribe = onSnapshot(q, (querySnapshot) => {
          setMessages(querySnapshot.docs)
      });
      

      因此:每次您收到 Firestore 通知 q 中的数据已更改时,您都会将数据传递给状态/UI 以进行渲染。

      【讨论】:

      • 我的查询不是这样,因为它有限制(5)。它是这样工作的。我加载最后 5 条消息,然后在发生更改时将新消息添加到状态中。但奇怪的是 setMessages 有效,但 messages 无效。
      • 啊,我错过了限制。但是您不是只添加更改的文档,而是添加所有 5 个。要正确处理仅更改,请迭代 querySnapshot.docChanges,如下所示:firebase.google.com/docs/firestore/query-data/…
      猜你喜欢
      • 2023-03-23
      • 2020-12-30
      • 1970-01-01
      • 2021-07-12
      • 2021-04-11
      • 2020-06-20
      • 1970-01-01
      • 2018-09-27
      • 2020-03-23
      相关资源
      最近更新 更多