我能够使Infinite Scroll与React Native和Firebase一起使用,但是在检索接下来的6个文档时存在问题(限制设置为6)。一旦刷新列表的末尾,它将返回另外6个,但是与之前的6个文档相同,这是6个文档。
每次渲染6条记录时,我都会增加startAt,并且startAt将以正确的数量增加。不知道我是否缺少某些东西,或者它可能是异步问题?
// Imports: Dependencies
import React, { Component } from "react";
import { ActivityIndicator, Dimensions, FlatList, View, SafeAreaView, StyleSheet } from 'react-native';
import * as firebase from 'firebase';
import 'firebase/firestore';
import firebaseConfig from '../config/config';
// Imports: Components
import UserSelector from '../components/UserSelector';
import TitleLarge from '../components/TitleLarge';
// Screen Dimensions
const { height, width } = Dimensions.get('window');
// Screen: Flat List (Users)
class FlatListUsers extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
startAt: 0,
limit: 6,
loading: false,
};
}
// Component Will Mount
componentWillMount = () => {
// Firebase: Initialize
firebase.initializeApp({
apiKey: `${firebaseConfig.apiKey}`,
authDomain: `${firebaseConfig.authDomain}`,
databaseURL: `${firebaseConfig.databaseURL}`,
projectId: `${firebaseConfig.projectId}`,
storageBucket: `${firebaseConfig.storageBucket}`,
messagingSenderId: `${firebaseConfig.messagingSenderId}`,
});
}
// Component Did Mount
componentDidMount = () => {
this.retrieveUsers();
}
// Retrieve Users
retrieveUsers = async () => {
try {
// Set State: Loading
this.setState({ loading: true });
// Firebase: Database + Settings
const db = firebase.firestore();
// Query
console.log('Fetching Users')
const query = await db.collection('users')
.where('company', '==', 'Google')
.orderBy('first_name')
.startAt(this.state.startAt)
.limit(this.state.limit);
// Query Snapshot
const querySnapshot = await query.get();
// Document Data
console.log('Document Data');
const documentData = querySnapshot.docs.map(document => document.data());
// console.log(documentData);
// Set State: Initial Query
if (this.state.startAt <= this.state.limit) {
// Set State
this.setState({
data: documentData,
startAt: this.state.startAt + this.state.limit + 1,
loading: false,
refreshing: false,
})
}
// Set State: Refreshing Queries
else {
// Set State
this.setState({
data: [...this.state.data, ...documentData],
startAt: this.state.startAt + this.state.limit + 1,
loading: false,
refreshing: false,
})
}
// Start At
console.log(`StartAt: ${this.state.startAt}`);
}
catch (error) {
console.log(error);
}
};
// Retrieve More Users
retrieveMore = async () => {
try {
// Set State + Retrieve Users
this.setState({
loading: true,
}, async () => {
await this.retrieveUsers();
})
// Set State
this.setState({
loading: false,
})
}
catch (error) {
console.log(error);
}
};
// Render Header
renderHeader = () => {
try {
return (
<View style={styles.activityIndicator}>
<TitleLarge title="Users" />
</View>
)
}
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={this.state.data}
renderItem={({ item }) => (
<UserSelector
key={(item, index) => {
return item.id;
}}
firstName={item.first_name}
lastName={item.last_name}
company={item.company}
/>
)}
keyExtractor={( item ) => {
return item.id;
}}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
onEndReached={this.retrieveMore}
onEndReachedThreshold={0}
/>
</SafeAreaView>
)
}
}
// Styles
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
height: height,
width: width,
borderTopWidth: 0,
borderBottomWidth: 0,
},
scrollView:{
height: 'auto',
},
UserContainer: {
width: width,
marginBottom: 7,
},
itemText: {
fontFamily: 'System',
fontSize: 17,
fontWeight: '400',
color: '#222222',
marginLeft: 16,
},
activityIndicator: {
paddingVertical: 20,
borderTopWidth: 0,
borderTopColor: '#CED0CE',
},
});
// Exports
export default FlatListUsers
答案 0 :(得分:0)
该查询获得相同的结果,因为它始终以相同的偏移量开始:startAt: 0
。
要解决此问题,请保持pageNumber
状态,并随着用户滚动前进,然后startAt: pageNumber*6
关于代码的其他一些注释:状态可以简化...
this.state = {
data: [],
limit: 6,
// startAt removed. start at the end of data
loading: false
};
不需要retrieveMore
。与retrieveUsers
相同。 retrieveUsers
可以简化...
// Retrieve Users
retrieveUsers = async () => {
try {
// Set State: Loading
this.setState({ loading: true });
// Firebase: Database + Settings
const db = firebase.firestore();
// Query
console.log('Fetching Users')
const query = await db.collection('users')
.where('company', '==', 'Google')
.orderBy('first_name')
.startAt(this.state.data.length)
.limit(this.state.limit);
// Query Snapshot
const querySnapshot = await query.get();
// Document Data
console.log('Document Data');
const documentData = querySnapshot.docs.map(document => document.data());
// console.log(documentData);
// Set State
this.setState({
data: [...this.state.data, ...documentData],
loading: false
})
}
catch (error) {
console.log(error);
}
};
请注意,startAt计算为已检索到的数据的长度。这也适用于数据数组为空的情况。请注意,在get
之后更新状态的逻辑对于第一个或第n个get都是相同的:将新数据追加到现有数据。
您不需要retrieveMore
。与retrieveUsers
相同。 retrieveUsers
可以简化...
// ...
onEndReached={this.retrieveUsers}
答案 1 :(得分:0)
Flatlist
可能调用您的检索方法两次。因此,请确保使用loading
道具来阻止该方法运行。
onEndReached={(foo)=>{
if (this.state.loading === false){
this.makeAPizza(foo);
}
}}