【发布时间】:2021-05-19 16:15:38
【问题描述】:
我正在构建一个包含聊天的 ReactNative 应用程序,我用来保存数据的数据库是 Firebase 的 Realtime DB。
当我导航到聊天屏幕时,首先我会加载一次已经存在的聊天消息:
const [messages, setMessages] = useState();
...
let chatRef = firebase.database().ref('chats/' + chatId);
let chatData = null;
useEffect(() => {
chatRef.once('value').then((snapshot) => {
if (snapshot.exists()) {
...
chatData = snapshot.val();
setMessages(chatData.messages.reverse());
...
} else {
console.log("No data available");
}
}).catch((error) => {
console.error(error);
});
},[]);
我在引用上使用 .once 方法,但我仍然必须使用 useEffect 来避免无限循环,因为我将聊天消息设置为状态,触发屏幕打印的原因再次调用 .once 方法,否则将再次调用。
但是当我希望到达数据库的新消息在已经打开的聊天屏幕中实时显示时,我的问题就来了。为此,我尝试执行以下操作:
let messagesRef = chatRef.child('messages');
messagesRef.limitToLast(1).on('child_added', (snapshot) => {
let data = snapshot.val();
if(snapshot.key > chatLen){
console.log("NEW MESSAGE IN THIS CHAT: "+data.text);
let auxMessages = messages;
auxMessages[-1] = data;
setMessages(auxMessages)
}else{
console.log("REPEATED NOTIFICATION OF MESSAGE: "+data.text);
}
});
作为 snapshot.key 是我刚刚收到事件的消息的编号,chatLen 是已经显示在屏幕上的聊天时长。 p>
在最后一段代码中,我尝试订阅新消息的创建,如果我收到一条消息的重复事件,我会忽略它(但我想知道为什么会发生这种情况),但如果它是新消息我想更新它在屏幕上显示的内容,所以我将它添加到状态中的消息中,但是我进入了一个我不知道如何打破的无限循环,因为我不知道如何以我的屏幕订阅新消息的方式放置另一个 useEffect 子句,但它不会在每次打印屏幕时都这样做,但同时,每次新事件到达时,它都会由代码处理最后一个“if”子句。
对不起我的英语,任何建议都将不胜感激,这是我第一次使用 firebase 实时数据库引用,我可能做错或理解错误。
【问题讨论】:
标签: firebase react-native firebase-realtime-database chat