【发布时间】:2021-04-11 22:21:49
【问题描述】:
免责声明:我希望我的描述一针见血,因为我在这个问题上花了很多时间。请在 cmets 中给我反馈以改进我的问题,以便您有足够的信息给我一个好的答案。我构建这个应用程序是为了支持一个电晕疫苗接种中心作为一个慈善项目,但我没有得到报酬,我尽量避免花钱阅读 Firestore。因此我想减少它们。
我有两个使用 ReactJS 构建的网络应用程序:
- 用户可以生成签到票
- 管理员可以签入用户。
1. 应用程序只有 Firestore 写入。每个用户一次写入。我不会更详细地介绍该应用程序,因为它不会有问题。
2. 应用程序在每个用户签入时有 1 次写入,而我在读取时遇到问题,因为应用程序 currentyl 很快就达到了每天 50.000 次免费读取。而且我只有 3000 个用户(蓝线是读,紫线是写):
Admin 应用具有三个视图:CheckInView、UserArchive 和 UserView。该应用程序使用带有一个 users 集合的 Firestore 数据库。我构建应用程序只是为了工作,现在我想改进代码以避免对 firestore 应用程序进行不必要的读取。
对于CheckInView,我需要.onSnapshot(),以便管理员无需手动刷新页面并自动查看新用户。它只读取未签入的用户 (.where("checkedin", "==", null))。
UserArchive 应显示已签入的所有 用户 (.where("checkedin", "!=", null))。它有一个输入字段来过滤/搜索特定用户。每天大约有 200-300 个用户,最多 10 个用户不同时签到。这意味着每天有 200-300 个新用户。因此,每天的阅读量增加了 200-300 次。
对于UserView,我再次阅读,但只有一个用户。我不太确定为什么我的应用程序如此努力地扩展读取。当您从UserView 回到UserArchive 时,可能会发生这种情况,因为它一次又一次地获取所有用户。
我可以在UserArchive 中从.onSnapshot() 切换到.get(),但我不确定是否可以通过问题解决。也许不会。
也许有人比我在 firestore 读取方面更有经验,并且可以检查我的代码并发现这么多读取的问题。
这是我的具有基本功能的 mutch 缩小代码:
import { useEffect, useState } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import firebase from "./firebase";
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/checkin" component={CheckInView} />
<Route exact path="/userview/:udi" component={UserView} />
<Route exact path="/userarchive" component={UserArchive} />
</Switch>
</Router>
</div>
);
}
export default App;
export const CheckInView = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("users")
.where("infected", "==", null)
.onSnapshot((fetchedUsers) => {
setUsers(fetchedUsers.docs.map((user) => user.data()));
});
return () => {
unsubscribe();
};
}, [setUsers]);
return (
<div>
<Link to="/userarchive">- Archive</Link>
{users.map((user) => (
<div key={user.uid}>
<Link to={`/userview/${user.uid}`}>{user.name}</Link>
</div>
))}
</div>
);
};
const UserArchive = () => {
const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("users")
.where("infected", "!=", null)
.onSnapshot((fetchedUsers) => {
setUsers(fetchedUsers.docs.map((user) => user.data()));
});
return () => {
unsubscribe();
};
}, [setUsers]);
return (
<div>
<Link to="/checkin">- CheckIn</Link>
<input
type="text"
value={search}
placeholder="Search..."
onChange={(e) => setSearch(e.target.value)}
/>
{users
.filter((e) => e.name.toLowerCase().includes(search.toLowerCase()))
.map((user) => (
<div key={user.uid}>
<Link to={`/userview/${user.uid}`}>{user.name}</Link>
</div>
))}
</div>
);
};
const UserView = ({ match }) => {
const [user, setUser] = useState();
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("users")
.doc(match.params.uid)
.onSnapshot((user) => {
setUser(user.data());
});
return () => {
unsubscribe();
};
}, [setUser, match.params.uid]);
return (
<>
<div>{user !== undefined ? user.name : "No Valid User."}</div>
<Link to="/checkin">Back</Link>
</>
);
};
将 one .onSnapshot() 添加到 App 组件并将其传递给所有视图并根据我的要求对其进行过滤是个好主意,例如:
-
users.fiter(e => e.checkedin === true)用户存档 -
users.fiter(e => e.checkedin === false)用于 CheckInView -
users.fiter(e => e.uid === march.params.uid)用于用户视图
【问题讨论】:
标签: reactjs firebase google-cloud-firestore