React钩子与firestore数据-30秒内读取1.1k(来自2个集合,其中3个文档具有2个属性)



我正在努力了解Cloud Firestore读取配额是如何工作的。我已经阅读了这篇文章和对它的回应。我的控制台是打开的,但我无法理解一个包含3个文档的集合是如何构成一个";繁忙控制台";。

我很难理解这些文档。

我在消防仓库有两个收藏品。每个都有3份文件。每个文档有2个属性。我正在使用这些属性填充"材质UI"中"自动完成"选择菜单中的选项。

在localhost中,我一直在运行该表单,以测试使用单个快照将这些属性放入自动完成选择菜单。在30秒内,这两个表单项目在firestore中产生了1.1万次阅读。

我想:

  1. 快照仅在firestore中的数据发生更改时更新。

  2. 通过使用取消订阅,钩子将停止侦听firestore中的更改。

  3. 通过将列表的状态添加为挂钩的依赖项(useEffect块末尾的orgList(,提高了firestore读取的效率:https://medium.com/javascript-in-plain-english/firebase-firestore-database-realtime-updates-with-react-hooks-useeffect-346c1e154219.

有人能看到通过仅使用2个输入项运行此表单生成1.1k读数的情况吗(目前整个应用程序中没有其他firestore调用(。

import React, { useState, useEffect } from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import firebase from "../../../../../firebase";
const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export default function CheckboxesTags() {
const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
// if (doc.exists) {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName,
location: doc.data().location
}));
setOrgList(orgList);
console.log("orglist", orgList)
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();


}, [orgList]);


return (
<div>

<Autocomplete
multiple
id="orgList options"
options={orgList}
disableCloseOnSelect
getOptionLabel={(option) => option.shortName}
renderOption={(orgList, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{orgList.shortName}  <span style={{marginRight: "4px", marginLeft: "4px"}}>-</span>
{orgList.location}
</React.Fragment>
)}
style={{ width: 500 }}
renderInput={(params) => (
<TextField {...params} 
variant="outlined" 
label="Select Organisation" 
placeholder="Acme Inc." 
/>
)}
/>
</div>
);
}

另一个表单与此完全相同,但它没有使用orgList,而是使用userList。否则,一切都是一样的(所以:2个集合,每个集合中有3个文档,每个文档中有2个属性(。

const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
// if (doc.exists) {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName,
location: doc.data().location
}));
setOrgList(orgList);
console.log("orglist", orgList)
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();


}, [orgList]);

根据我的理解,我们告诉React,如果orgList发生变化,请运行此效果。效果如下:

  1. 致电Firestore
  2. 映射<-这导致了这个问题,因为我们正在创建一个新的数组
  3. setOrgList(orgList)<-这就是问题所在

现在orgList已经更改,React必须重新运行效果。我创建了一个类似的stackblitz(来自材料ui的主页(,它可能会导致这个问题。看见https://stackblitz.com/edit/evsxm2?file=demo.js.查看控制台并注意到它一直在运行。

解决此问题的可能方法

如果我们只需要一次数据。。。

建议1:在开始使用时设置if条件效果

const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
if (orgList.length > 0) {
return; // we already have data, so no need to run this again
}
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName,
location: doc.data().location
}));
setOrgList(orgList);
console.log("orglist", orgList)
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();


}, [orgList]);

建议2如果我们真的需要倾听实时变化。。。?(我还没有测试过(

const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName,
location: doc.data().location
}));
setOrgList(orgList);
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();


}, []); // we don't depend on orgList because we always overwrite it whenever there's a snapshot change

orgList不应在useEffect钩子中声明为依赖项,您真正想要的是setOrgList

我相信你在这里触发了一个无限循环,因为钩子每次CCD_;更新的";在钩子内部,重新触发它。然而,它从来没有在钩子内部使用过,看起来这真的不是你想要的。如果您想仅在"上设置快照侦听器;安装件";然后简单地使用一个空的依赖关系列表或者研究记忆策略。你可能想要的是:

useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName,
location: doc.data().location
}));
setOrgList(orgList);
setLoading(false);
}, () => {
setError(true)
setLoading(false);
});
return () => unsubscribe();
}, []); // <----- empty dependency means it only runs on first mount

编辑:

可能的困惑是,你认为如果orgList内部的数据看起来相同,那么React应该知道不要重新触发,然而useEffect并不像你想象的那么聪明,所以你必须自己做一些工作来帮助它。由于orgList是一个对象,它实际上是一个引用,并且这个引用正在重复更新。关于te(按值(与引用(按参考(的一些潜在澄清:JavaScript(按引用(与(按值

对许多人有效的解决方案是使用缓存,而不是不断地从Firestore读取。

例如,直接从Firebase文档

var getOptions = {
source: 'cache'
};
// Get a document, forcing the SDK to fetch from the offline cache.
docRef.get(getOptions).then(function(doc) {
// Document was found in the cache. If no cached document exists,
// an error will be returned to the 'catch' block below.
console.log("Cached document data:", doc.data());
}).catch(function(error) {
console.log("Error getting cached document:", error);
});

这篇文章的内容也很丰富,并且有一个代码示例(虽然是Java for Android(,我发现它对理解如何减少对Firestore的读取量非常有用。

对于其他想要学习的人,我刚刚发现了这篇博客文章,它也有助于理解依赖数组:https://maxrozen.com/learn-useeffect-dependency-array-react-hooks/

相关内容

  • 没有找到相关文章

最新更新