【发布时间】:2021-08-04 14:34:32
【问题描述】:
TL;DR
我正在开发聊天列表功能,就像任何大型社交网络一样,我在 React Native 状态管理方面遇到了问题,因为 very common problem with Firestore onSnapshot "in" conditions.
作为解决方法,我正在从状态数组生成批处理。onSnapshot 根据此类批处理更改状态数组,但是每次更改后我都无法刷新批处理。
完整说明
其中一个复杂性是我必须以 Firebase 尚不支持的方式调节来自 Firestore 的实时更新:
const watchedGroups = db.collection('group').where('__name__', 'in', groupArray?.map(({ id }) => id));
unsubscribeListener = watchedGroups.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
//...
(请注意群组 = 聊天)
这种方法的问题是Firestore does not support a IN condition (groupArray) with more than 10 elements 和这个代码块会在情况发生时崩溃。
为了解决这个问题,我在不违反此类限制的批次中联系了groupArray:
const [recentChats, setRecentChats] = useState([]);
// ...
useFocusEffect(useCallback(() => {
const grupos = [...recentChats];
if (grupos && grupos.length > 0) {
handleRefreshSuscriptions();
const collectionPath = db.collection('group');
while (grupos.length) {
const batch = grupos.splice(0, 10);
console.log(">> QUERYING", batch?.length, batch.map(({ lastMsgForMe }) => lastMsgForMe))
const unsuscribe = collectionPath.where(
'__name__',
'in',
[...batch].map(({ id }) => id)
).onSnapshot((querySnapshot) => {
if (querySnapshot !== null) {
querySnapshot.forEach((doc) => {
const validGroup = batch.find(grupo => doc.id == grupo.id);
if (validGroup) {
lastMsg(doc.id).then((lastM) => {
console.log(batch.map(({ lastMsgForMe }) => lastMsgForMe))
if (validGroup.lastMsgForMe !== doc.data().recentMessage.messageText) {
mergeChat({
...validGroup,
messageText: doc.data().recentMessage.messageText,
lastMsgForMe: lastM.messageText,
dateMessageText: lastM.sentAt,
viewed: lastM.viewed
});
}
}).catch(error => console.log(error));
}
})
}
})
setRefreshSuscription(prevState => [...prevState].concat(unsuscribe))
}
}
return () => {
handleRefreshSuscriptions();
}
}, [recentChats.length]));
它(几乎)完美地工作,每次更改都成功地到达视图。但是,有一个问题,这是我收到第一次更新时的日志:
// Initialization (12 groups shown, 2 batches)
>> QUERYING 10 ["B", "Dddffg", "Dfff", ".", null, "Hvjuvkbn", "Sdsdx", "Vuvifdfhñ", "Ibbijn", "asdasdasd"]
>> QUERYING 2 ["Veremoss", "Hjjj"]
// Reception of a message "C" that updates last message shown ("B") of first group in the list.
["B", "Dddffg", "Dfff", ".", null, "Hvjuvkbn", "Sdsdx", "Vuvifdfhñ", "Ibbijn", "asdasdasd"] //several repetitions of this log, i've erased it for simplicity
update idx 0 - B -> C
此时,没有任何明显的问题。但是,如果我继续与其他组交互,然后在收到上述组的消息时注意日志,我会看到:
["B", "Dddffg", "Dfff", ".", null, "Hvjuvkbn", "Sdsdx", "Vuvifdfhñ", "Ibbijn", "asdasdasd"]
update idx 1 - Bbnnm -> Bbnnm // unexpected
update idx 0 - 12 -> 12 // unexpected
update idx 2 - C -> D // expected
请注意,当我已经收到该组的“C”和“D”消息时,该批次仍然显示“B”。这个问题在其他两组上重复出现,正因为如此,现在我得到了一个真正的变化和另外两个误报。
问题在于,由于批次的生成方式,onSnapshot 内部的batch 内容始终相同。这会导致与自批次生成以来已更新的组一样多的错误“更新”,每条收到的消息。
如何在onSnapshot 中保持批次是最新的?
【问题讨论】:
标签: javascript reactjs firebase google-cloud-firestore