我的 React-Native 应用程序是否需要分页、延迟加载或 none?
Do I need Pagination, Lazy Loading or none in my React-Native app?
我正在 React-Native 中实现一个应用程序,我从 Cloud-Firestore 中获取 "restaurants" 作为文档,我还使用 onSnapshot() 侦听器。当该应用程序准备好发布时,最多可能会有大约 3000 家餐厅。关于这件事,我有几个问题要问。
-我是否需要实施 Pagination/Lazy 加载以获得更好的用户体验和更低的成本,或者 3000 不是一个大数字,因此不会对性能产生太大影响?!
-如果我确实需要实现其中之一,我应该实现哪一个?
-如果我不需要,那么有没有办法在 React-Native 中获取时压缩 JSON 数据,从而节省 space?然后在用户要求时解压。
实现延迟加载后用户可以搜索餐厅吗?
编辑:
我设法实现了延迟加载并完美地工作,但是,使用 snapshot()
侦听器将使延迟加载变得毫无意义,但我必须使用它,因为我需要实时获取新的 "restaurants" 或“订单. 那么,除了 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 侦听器,因为它会 return 每次发生变化时您的整个集合,这否定了使用分页的全部意义
编辑:
关于实时更新:这取决于你想实时获取什么。是只有您加载的那些餐厅还是所有餐厅?假设您的数据库中有 1.000.000 家餐厅,您肯定不想查询所有餐厅以获取实时更新。仅刷新当前加载的那些在 firestore 中是非常昂贵的操作,因为每次可见的餐厅发生变化时(例如,当您滚动页面时),它都需要取消和创建新的订阅。所以这两种变体都不是一个选项
您应该重新考虑您的应用设计 - 例如您真的需要实时跟踪每家注册餐厅的订单吗?也许你只想要那些你是雇员的人,或者只想要那些离你最近的人?也许您应该重组您的数据库以将订单与餐厅分开,这样您就可以在仍然延迟加载餐厅的同时收听订单?
我正在 React-Native 中实现一个应用程序,我从 Cloud-Firestore 中获取 "restaurants" 作为文档,我还使用 onSnapshot() 侦听器。当该应用程序准备好发布时,最多可能会有大约 3000 家餐厅。关于这件事,我有几个问题要问。
-我是否需要实施 Pagination/Lazy 加载以获得更好的用户体验和更低的成本,或者 3000 不是一个大数字,因此不会对性能产生太大影响?!
-如果我确实需要实现其中之一,我应该实现哪一个?
-如果我不需要,那么有没有办法在 React-Native 中获取时压缩 JSON 数据,从而节省 space?然后在用户要求时解压。
实现延迟加载后用户可以搜索餐厅吗?
编辑:
我设法实现了延迟加载并完美地工作,但是,使用 snapshot()
侦听器将使延迟加载变得毫无意义,但我必须使用它,因为我需要实时获取新的 "restaurants" 或“订单. 那么,除了 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 侦听器,因为它会 return 每次发生变化时您的整个集合,这否定了使用分页的全部意义
编辑:
关于实时更新:这取决于你想实时获取什么。是只有您加载的那些餐厅还是所有餐厅?假设您的数据库中有 1.000.000 家餐厅,您肯定不想查询所有餐厅以获取实时更新。仅刷新当前加载的那些在 firestore 中是非常昂贵的操作,因为每次可见的餐厅发生变化时(例如,当您滚动页面时),它都需要取消和创建新的订阅。所以这两种变体都不是一个选项
您应该重新考虑您的应用设计 - 例如您真的需要实时跟踪每家注册餐厅的订单吗?也许你只想要那些你是雇员的人,或者只想要那些离你最近的人?也许您应该重组您的数据库以将订单与餐厅分开,这样您就可以在仍然延迟加载餐厅的同时收听订单?