I have a database listener on my app that updates my data state every time a user posts something. When I get the new post I update my state called "posts" which is an array with all the items that the FlatList renders.
The problem is that after updating the state I can't see the new post in the top of the list until I go down (to the footer of the list) and then back to the top.
My FlatList code is:
const keyExtractor = ({id}) => id
...
const renderItem = ({ item }) => {
const {
uri,
description,
location,
width,
height,
likes,
comments,
date,
} = item;
return (
<Card
uri={uri}
description={description}
location={location}
width={width}
height={height}
likes={likes}
date={date}
/>
);
};
return (
<FlatList
data={data} // data is the post state of the parent
renderItem={renderItem}
keyExtractor={keyExtractor}
initialNumToRender={15}
windowSize={WINDOW_HEIGHT * 2}
maxToRenderPerBatch={15}
updateCellsBatchingPeriod={50}
removeClippedSubviews={false}
ListFooterComponent={
isLoading ? (
<View style={styles.footer}>
<Loading type="ios" size={18} color={colors.gray} />
</View>
) : null
}
/>
);
}
And this is how I update the post state (in the parent component of the flat list)
function Posts(props) {
const [posts, setPosts] = useState([]);
useEffect(() => {
const { firebase } = props;
let postsArray = [];
// Realtime database listener
const unsuscribe = firebase
.getDatabase()
.collection("posts")
.doc(firebase.getCurrentUser().uid)
.collection("userPosts")
.orderBy("date") // Sorted by upload date
.onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === "added") {
// Get the new post
const newPost = change.doc.data();
// Add the new post to the posts list
postsArray.unshift(newPost);
}
});
// Reversed order so that the last post is at the top of the list
setPosts(postsArray);
});
/* Pd: At the first time, this function will get all the user's posts */
return () => {
// Detach the listening agent
unsuscribe();
};
}, []);
return (
<View style={styles.container}>
<CardList data={posts} />
</View>
);
}
The issue could be caused by the way, you append new posts:
postsArray.unshift(newPost)
..
setPosts(postsArray)
It doesn't seem to affect the reference of postsArray
, thus no state updates happen, no re-renders seen .
You may try, instead:
setPosts([...postsArray])
Assign a marker property extraData
for telling the list to re-render (since it implements PureComponent). If any of your renderItem, Header, Footer, etc. functions depend on anything outside of the data prop, stick it here and treat it immutably.
Your update would be:
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
extraData={/* You need to create another state variable which also changes when a post is added*/}
/>
For more information visit here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.