问题
I am having trouble with appending my data when I call my fetch method a second time. On the initial render, my component fetches data from my database and stores it in my followingData state. Then, when I scroll to the bottom, I call my fetchData function again, but instead of my new data being appended in to the followingData state, it replaces it, and now only the new data is displayed on the my screen.
Here is the code:
function Following({route, navigation}) {
const [followingData, setfollowingData] = useState([]);
const [loading, setLoading] = useState(true);
const [lastVisible, setLastVisible] = useState();
const fetchData = () => {
const dataaRef = firestore().collection('usernames');
const dataRef = firestore().collection('usernames');
dataRef
.doc(route.params.username.toLowerCase())
.collection('Following')
.onSnapshot(() => {
dataaRef
.doc(route.params.username.toLowerCase())
.collection('Following')
.orderBy('followedAt')
.startAfter(lastVisible || 0)
.limit(7)
.get()
.then((snapshot) => {
snapshot.empty
? null
: setLastVisible(
snapshot.docs[snapshot.docs.length - 1].data().followedAt,
);
let promises = [];
snapshot.forEach((doc) => {
const data = doc.data();
promises.push(
data.path.get().then((res) => {
const userData = res.data();
return {
profileName: doc.id ? doc.id : null,
displayName: userData.displayName
? userData.displayName
: null,
followerCount:
userData.followers !== undefined ? userData.followers : 0,
followingCount:
userData.following !== undefined ? userData.following : 0,
imageUrl: userData.imageUrl ? userData.imageUrl : null,
};
}),
);
});
Promise.all(promises).then((res) => {
setfollowingData(res);
});
setLoading(false);
});
});
};
useEffect(() => {
const dataRef = firestore().collection('usernames');
const cleanup = fetchData();
return cleanup;
}, [route.params.username]);
return (
<>
<View
style={styles}>
<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Icon name="menu" color="#222" size={30} />
</TouchableOpacity>
<Text style={{left: width * 0.05}}>Following</Text>
</View>
{loading ? (
<ActivityIndicator size="large" color="black" />
) : (
<>
<FolloweringScreens
data={followingData}
screen={'Following'}
username={route.params.username}
navigation={navigation}
fetchData={fetchData}
/>
</>
)}
</>
);
}
export default Following;
The child component looks like this, where the fetchData is being called upon when scrolling to the end:
function FolloweringScreens({
data,
screen,
username,
navigation,
fetchData,
setNext,
}) {
return (
<>
<FlatList
scrollEnabled={true}
onEndReachedThreshold={0}
onEndReached={fetchData} <<-- CALLING FETCHDATA AGAIN TO GET MORE DATA
data={data}
keyExtractor={(i, index) => index.toString()}
renderItem={({item, index}) => {
return (
(I use my data here)
);
}}
/>
</>
);
}
export default FolloweringScreens;
回答1:
If you just want to append the new data, then it is better if you use a callback function in your setState:
Promise.all(promises).then(res => {
setfollowingData(oldState => ({...oldState, ...res}));
});
Here you take all the values from the old state, put it in a new object and add the new data to it. If your state is an array, you would have to exchange the {} with []:
Promise.all(promises).then(res => {
setfollowingData(oldState => ([...oldState, ...res]));
});
UPDATE: Added Example
来源:https://stackoverflow.com/questions/65918350/how-to-append-data-when-fetching-a-second-time