【发布时间】:2021-10-27 11:57:36
【问题描述】:
我在我的应用程序中实现了一个聊天屏幕,下面的代码代表了代码的重要示例,我注意到关于数据使用的一些东西非常奇怪。该代码是一个稍长的代码示例,但我会在之后解释它。
const CountryChat = props =>{
var chosenLanguage = useSelector(state => state.myLanguage.myLanguage);
const countryId = props.navigation.getParam("countryId");//already upper case so no worries about correct firestore adress
const countryName = props.navigation.getParam("countryName");
const userId = useSelector(state => state.auth.userId);
const [TItext, setTItext] = useState("");
const [chatmessages, setChatMessages] = useState(() => []);//dummydata so FlatList wont crash because messages are empty during first renderprocess
const [refreshFlatlist, setRefreshFlatList] = useState(false);
const [myProfilePic, setMyProfilePic] = useState(null);
useEffect(() => {
downloadProfilePic();
var loadnewmessages = firebase.firestore().collection("group_rooms").doc("group_rooms").collection(`${countryId}`).orderBy("timestamp").limit(30).onSnapshot((snapshot) => {
var newmessages = [];
var deletedmesssages = [];
snapshot.docChanges().forEach((change) => {
if(change.type === "added"){
newmessages.push({
counter: change.doc.data().counter,
sender: change.doc.data().sender,
timestamp: change.doc.data().timestamp.toString(),
value: change.doc.data().value,
displayedTime: new Date(change.doc.data().displayedTime),
senderProfilePic: change.doc.data().senderProfilePic
})
};
if(change.type === "removed"){
deletedmesssages.push({
counter: change.doc.data().counter,
sender: change.doc.data().sender,
timestamp: change.doc.data().timestamp.toString(),
value: change.doc.data().value,
displayedTime: new Date(change.doc.data().displayedTime),
senderProfilePic: change.doc.data().senderProfilePic
})
};
})
if(newmessages.length > 0){
setChatMessages(chatmessages => {
return chatmessages.concat(newmessages)
});
};
if(deletedmesssages.length > 0){
setChatMessages(chatmessages => {
var modifythisarray = chatmessages;
let index = chatmessages.map(e => e.timestamp).indexOf(`${deletedmesssages[0].timestamp}`);
let pasttime = Date.now() - parseInt(modifythisarray[index].timestamp);
modifythisarray.splice(index, 1);
if(pasttime > 300000){
return chatmessages
}else{
return modifythisarray
}
});
setRefreshFlatList(refreshFlatlist => {
//console.log("Aktueller Status von refresher: ", refreshFlatlist);
return !refreshFlatlist
});
}
newmessages = [];
deletedmesssages = [];
});
return () => { //for removing listeners
try{
loadnewmessages();
}catch(error){console.log(error)};
}
}, []);
const pushMessagetoDB = async (filter, imageName) => {
//sending message to the chatroom in Firestore
if(filter == 1){
await firebase.firestore().collection("group_rooms").doc("group_rooms").collection(`${countryId}`).add({
"counter": 1,
"sender": userId,
"timestamp": Date.now(),
"value": TItext,
"displayedTime": (new Date()).toISOString(),
"senderProfilePic": myProfilePic
})
.then(() => {
console.log("Chat written in DB!");
})
.catch((error) => {
console.error("Error writing Chat into DB: ", error);
});
}else{
await firebase.firestore().collection("group_rooms").doc("group_rooms").collection(`${countryId}`).add({
"counter": 2,
"sender": userId,
"timestamp": Date.now(),
"senderProfilePic": myProfilePic,
"value": await firebase.storage().ref(`countrychatimages/${countryId}/${imageName}`).getDownloadURL().then((url) => {
return url
}).catch((error) => { //incase something bad happened
console.log(error);
})
})
.then(() => {
console.log("Image passed to DB!");
})
.catch((error) => {
console.error("Error passing Image to DB: ", error);
});
}
};
你可以在这里看到我的监听器loadnewmessages,它在我的 useEffect 中被调用。此侦听器下载聊天中最近的 30 条消息并将它们存储在一个状态中。聊天完美无缺,我什至可以发送消息(将文档存储在代表聊天的集合内的 firestore 上)。在我离开屏幕后,useEffect 中的return 被触发,我的监听器被取消。
我的问题是:我来回走了大约 4 次,我的收藏中有 6 条消息。完成此操作后,我关闭了我的应用程序并在 firebase 的“使用和计费”中检查了我的使用情况,突然发现我有大约 25 次读取。我希望我的听众只会下载一次包含文档的集合,并且即使我离开屏幕也会保留在手机上,而不是当我检查屏幕时我总是重新下载它,即在我在我的 firebase 控制台中看到我的使用情况后,我假设正在发生的事情。如果我启动我的应用并获得 100 或更多用户,我的账单就会以这种方式激增。
我知道我分离了我的监听器并重新启动它,但我希望 firebase 能够维护手机上已经加载的数据,所以我(如果不会写入新文件)我只读取 1 次,因为查询运行时没有加载任何新的数据。
有人可以向我解释我做错了什么或者我可以如何改进我的代码以减少读取吗?如何更改我的代码以使其保持高效并且不下载已加载的数据?将读取保持在低水平对我来说真的很重要,我在控制它方面遇到了很大的问题,而且我的钱非常有限。
【问题讨论】:
标签: firebase react-native google-cloud-firestore react-hooks use-effect