每当我通过 onSnapshot 从消息集合中提取新消息时,我的消息收件箱都不会重新呈现。
正如我在开发工具中看到的那样,我可以确认新消息肯定存储在 auseRef
中,但是该消息没有进入 DOM。
我遵循zustand's
了解释使用 ref 的文档,并且建议使用他们的订阅方法来重复发生状态更改:https ://github.com/pmndrs/zustand#transient-updates-for-often-occuring-state-changes
谁能看到我可能出错的地方?
获取对话和实时更新的消息页面:
import { useState, useEffect, useRef } from "react";
import "./Messages.scss";
import { db } from "../../firebase";
import { Message, Conversation } from "../../Interfaces/Interfaces";
import MessagesHeader from "./Components/MessagesHeader/MessagesHeader";
import MessagesConversations from "./Components/MessagesConversations/MessagesConversations";
import create from "zustand";
import authStore from "../../Global/AuthState/AuthStore";
interface ConversationsStore {
conversations: Array<Conversation>;
setConversations: (newConversations: Array<Conversation>) => void;
}
const conversationsStore = create<ConversationsStore>((set) => ({
conversations: [],
setConversations: (newConversations: Array<Conversation>) =>
set({ conversations: newConversations }),
}));
function Messages() {
const currentUser = authStore((state) => state.currentUser);
const [subToUpdates, setSubToUpdates] = useState<boolean>(false);
const [initialDone, setInitialDone] = useState<boolean>(false);
//create the initial conversations ref
const conversationsRef = useRef<Array<Conversation>>(
conversationsStore.getState().conversations
);
const conversations = conversationsStore((state) => state.conversations);
const setConversations = conversationsStore(
(state) => state.setConversations
);
//zustand's recommended subscribe useEffect to re-render whenever a new conversation enters the db
useEffect(
() =>
conversationsStore.subscribe(
(state) => (conversationsRef.current = state.conversations)
),
[]
);
//get the current conversations that the user is in
useEffect(() => {
if (currentUser) {
let initialConversations: Array<Conversation> = [];
const conversationsRef = db.collection("conversations");
const getInitialConversations = async () => {
const conversationsSnapshot = await conversationsRef
.where("users", "array-contains", currentUser.uid)
.orderBy("latestMessageDate", "desc")
.get();
conversationsSnapshot.forEach((doc) => {
let tempConversation: Conversation = doc.data() as Conversation;
tempConversation.conversationId = doc.id;
initialConversations.push(tempConversation);
setConversations(initialConversations);
});
};
getInitialConversations().then(() => setSubToUpdates(true));
}
}, [currentUser]);
//after the initial load, listen to changes in the firestore collection
useEffect(() => {
if (subToUpdates && currentUser && !initialDone) {
setInitialDone(true);
} else if (subToUpdates && currentUser && initialDone) {
const conversationsRef = db.collection("conversations");
return conversationsRef
.where("users", "array-contains", currentUser.uid)
.orderBy("latestMessageDate", "desc")
.limit(1)
.onSnapshot((querySnapshot) => {
console.log("new conversation found");
querySnapshot.forEach((doc) => {
{
/*
let tempConversations = conversations?.filter(
(currentConversation) =>
currentConversation.conversationId == doc.id
);
*/
}
let tempConversations = conversations;
let tempConversation: Conversation = doc.data() as Conversation;
tempConversation.conversationId = doc.id;
tempConversations?.push(tempConversation);
setConversations(tempConversations);
});
});
}
}, [subToUpdates, initialDone]);
return (
<div className="messages">
{conversations.length > 0 &&
conversations.map((conversation, index) => (
<h4 key={index}>{conversation.latestMessage.message}</h4>
))}
<MessagesHeader />
<MessagesConversations
conversations={conversationsRef.current}
filterByUnread={false}
/>
</div>
);
}
export default Messages;
映射对话并显示它们的收件箱对话容器:
import React from "react";
import "./MessagesConversations.scss";
import MessagesConversationsConversation from "./Components/MessagesConversationsConversation/MessagesConversationsConversation";
import { Conversation } from "../../../../Interfaces/Interfaces";
interface Props {
conversations: Array<Conversation> | undefined;
filterByUnread: boolean;
}
function MessagesConversations({ conversations, filterByUnread }: Props) {
return (
<div className="messagesConversations">
{conversations !== undefined &&
(conversations?.length > 0 ? (
conversations.map((conversation) => (
<MessagesConversationsConversation
conversation={conversation}
key={`conversation__${conversation.conversationId}`}
/>
))
) : (
<h4>No messages</h4>
))}
</div>
);
}
export default MessagesConversations;