Я реализовал код, который прослушивает мои документы БД, и когда добавляется новый, приложение отображает его как элемент в моем FlatList.
У меня проблема в том, что каждый раз, когда я обновляю данные FlatList, уже визуализированные элементы повторно визуализируются снова и снова ...
Поскольку мой исходный код сложен, я создал Snack: https://snack.expo.io/@victoriomolina / flatlist-re-renders-all-components
Думаю, проблема в том, что я обновляю состояние, используя неглубокую копию существующего массива, но я делаю это просто для повторного рендеринга FlatList при добавлении новых элементов (я не Я не хочу повторно отображать уже отрисованные элементы) .
Спасибо, я очень признателен за вашу помощь.
Pd: В моем исходном коде компоненты FlatList расширяются React.PureComponent
Мой настоящий код
Часть извлечения
const [posts, setPosts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
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]); // Shallow copy of the existing array -> Re-render when new posts added
setIsLoading(false);
});
/* Pd: At the first time, this function will get all the user's posts */
return () => {
// Detach the listening agent
unsuscribe();
};
}, []);
FlatList
<FlatList
data={data}
keyExtractor={keyExtractor}
legacyImplementation={false}
numColumns={1}
renderItem={this.renderItem}
getItemLayout={this.getItemLayout}
initialNumToRender={12}
windowSize={40}
maxToRenderPerBatch={15}
updateCellsBatchingPeriod={50}
removeClippedSubviews
ListFooterComponent={this.renderFooter()}
/>
Метод элемента рендеринга
renderItem = ({ item, index }) => {
const {
images,
dimensions,
description,
location,
likes,
comments,
date,
} = item;
return (
<View
key={index}
onLayout={({ nativeEvent }) => {
this.itemHeights[index] = nativeEvent.layout.height;
}}
>
<Card { /* Extends React.PureComponent */ }
images={images}
postDimensions={dimensions}
description={description}
location={location}
likes={likes}
comments={comments}
date={date}
/>
</View>
);
};