我正在React-Native中实现一个应用程序,在该应用程序中,我从Cloud-Firestore提取“餐厅”作为文档,并且我也在使用onSnapshot()侦听器。准备好启动该应用程序时,大概将有大约3000家餐厅。关于这个问题,我有几个问题要问。
-我是否需要实现分页/延迟加载以获得更好的UX和更低的成本,或者3000不是一个很大的数字,因此它不会对性能产生太大影响!!
-如果我确实需要实现其中之一,我应该实现哪一个?
--如果我不需要,那么在React-Native中进行提取时是否有一种压缩JSON数据的方式,从而节省了空间?然后在用户要求时解压缩。
用户可以在实施延迟加载的同时搜索餐厅吗?
编辑:我设法实现了延迟加载及其完美的工作,但是,使用snapshot()
侦听器将使延迟加载毫无意义,但是我必须使用它,因为我需要获取实时的新“餐厅”或“订单”。否则我可以使用snapshot()
代替吗?或者也许仍然可以使用snapshot()
,但对代码进行少量更改?
第二个问题:解决了上述问题后,我可以执行餐厅搜索吗?知道我正在使用延迟加载,这似乎很棘手。
componentDidMount() {
try {
// Cloud Firestore: Initial Query
this.retrieveData();
}
catch (error) {
console.log(error);
}
};
retrieveData = () => {
try {
this.setState({
loading: true
})
var initialQuery = firebase.firestore().collection('restaurants')
.orderBy('res_id')
.limit(this.state.limit)
//let documentSnapshots = await initialQuery.get();
initialQuery.onSnapshot((documentSnapshots => {
var All = documentSnapshots.docs.map(document => document.data());
var lastVisible = All[All.length - 1].res_id;
this.setState({
All: All,
lastVisible: lastVisible,
loading: false,
});
}));
}
catch (error) {
console.log(error);
}
};
retrieveMore = async () => {
try {
// Set State: Refreshing
this.setState({
refreshing: true,
});
// Cloud Firestore: Query (Additional Query)
var additionalQuery = await firebase.firestore().collection('restaurants')
.orderBy('res_id')
.startAfter(this.state.lastVisible)
.limit(this.state.limit)
// Cloud Firestore: Query Snapshot
var documentSnapshots = await additionalQuery.get();
// Cloud Firestore: Document Data
var All = documentSnapshots.docs.map(document => document.data());
// Cloud Firestore: Last Visible Document (Document ID To Start From For Proceeding Queries)
var lastVisible = All[All.length - 1].res_id;
// Set State
this.setState({
All: [...this.state.All, ...All],
lastVisible: lastVisible,
refreshing: false,
});
console.log('Retrieving additional Data', this.state.All);
}
catch (error) {
console.log(error);
}
};
// Render Header
renderHeader = () => {
try {
return (
<Text style={styles.headerText}>Items</Text>
)
}
catch (error) {
console.log(error);
}
};
// Render Footer
renderFooter = () => {
try {
// Check If Loading
if (this.state.loading) {
return (
<ActivityIndicator />
)
}
else {
return null;
}
}
catch (error) {
console.log(error);
}
};
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
// Data
data={this.state.All}
// Render Items
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Text>(ID: {item.res_id}) {item.rest_name} {item.rest_location}</Text>
</View>
)}
// Item Key
keyExtractor={(item, index) => String(index)}
// Header (Title)
ListHeaderComponent={this.renderHeader}
// Footer (Activity Indicator)
ListFooterComponent={this.renderFooter}
// On End Reached (Takes a function)
onEndReached={this.retrieveMore}
// How Close To The End Of List Until Next Data Request Is Made
onEndReachedThreshold={0.1}
// Refreshing (Set To True When End Reached)
refreshing={this.state.refreshing}
/>
</SafeAreaView>
)
}
在这种情况下,分页和延迟加载是同一回事。您将在获取新数据时切换页面或无限滚动,直到没有更多数据可获取为止。无论哪种情况,都需要它。看这里https://firebase.google.com/docs/firestore/query-data/query-cursors
由于分页只是您查询数据的一种方式,它对您如何以其他方式使用此数据没有影响,这意味着在正确设置数据库设计和安全规则的情况下,确保可以搜索餐厅
虽然不知道您是否应该使用onSnapshot侦听器,因为每次发生更改时它将返回您的整个集合,这否认了使用分页的全部意义
编辑:
关于实时更新:这取决于您要实时获取的内容。仅仅是您已装载的那些餐馆还是全部?想象一下,您的数据库中有1.000.000家餐厅,您肯定不想查询所有餐厅以获得实时更新。在Firestore中,仅刷新当前加载的内容是非常昂贵的操作,因为每次可见餐厅更改时(例如,滚动页面时),都需要取消并创建新的订阅。因此,这两个变体都不是一个选项
您应重新考虑您的应用设计-例如,您真的需要实时跟踪每个注册餐厅的订单吗?也许您只想要那些您所在的公司,或者只想要您附近的公司?也许您应该重组数据库以使订单与餐厅分开,这样您就可以在仍然懒惰地加载餐厅的同时侦听订单?