[英]"VirtualizedList: You have a large list that is slow to update" warning even though all components are optimized
[英]React Native - VirtualizedList: You have a large list that is slow to update
我的 VirtualizedList(無限滾動)遇到了嚴重的性能問題......我一直在關注 這個以改進它,但仍然工作很慢。
當我向下滾動時,UI 線程從 60fps 到 30fps,JS 線程從 60fps 到 10/20fps(有時到 0fps)。 在 iOS (iPhone 6) 上它似乎比在我的 Android (Samsung Galaxy S8+) 上流暢
我的 VirtualizedList 正在渲染具有不同高度的項目,並在到達終點時獲取數據。 我的項目從 React.PureComponent 擴展,因為它是推薦的:
VirtualizedList:您有一個更新緩慢的大列表 - 確保您的 renderItem 函數呈現遵循 React 性能最佳實踐的組件,如 PureComponent、shouldComponentUpdate 等。 Object { "contentLength": 20720, "dt": 532, "prevDt" : 2933, }
當我向下滾動大約 20 個項目時會出現這個問題......
這是 VirtualizedList 的代碼:
const keyExtractor = ({ id }) => id;
...
getItem = (data, index) => data[index];
getItemCount = (data) => data.length;
renderItem = ({ item, index }) => {
const {
images,
dimensions,
description,
location,
likes,
comments,
date,
} = item;
return (
<Card
images={images}
postDimensions={dimensions}
description={description}
location={location}
likes={likes}
comments={comments}
date={date}
/>
);
};
<VirtualizedList
data={data}
getItem={this.getItem}
getItemCount={this.getItemCount}
keyExtractor={keyExtractor}
listKey={listKey}
legacyImplementation={false}
numColumns={1}
renderItem={this.renderItem}
initialNumToRender={MAX_POSTS_TO_RETRIEVE_LENGTH} // 10
windowSize={32}
maxToRenderPerBatch={15}
updateCellsBatchingPeriod={50}
removeClippedSubviews={false}
ListFooterComponent={this.renderFooter}
ListEmptyComponent={ListEmptyComponent}
onEndReached={onEndReached}
onEndReachedThreshold={0.5}
/>
Pd:我渲染的每個項目都有一個唯一的 ID。
我試圖為 List 實現我自己的 getItemLayout 方法,但由於某種原因它不能正常工作。
警告:失敗的框架類型:框架
frame.length
在VirtualizedList.getItemLayout
被標記為 required ,但其值為undefined
。
itemHeights = [];
getItemLayout = (data, index) => {
const length = this.itemHeights[index];
const offset = this.itemHeights.slice(0,index).reduce((a, c) => a + c, 0)
return {length, offset, index}
}
renderItem = ({ item, index }) => {
const {
images,
dimensions,
description,
location,
likes,
comments,
date,
} = item;
return (
<View onLayout={(event) => this.itemHeights[index] = event.nativeEvent.layout.height}>
<Card
images={images}
postDimensions={dimensions}
description={description}
location={location}
likes={likes}
comments={comments}
date={date}
/>
</View>
);
};
<VirtualizedList
data={data}
getItem={this.getItem}
getItemCount={this.getItemCount}
getItemLayout={this.getItemLayout}
keyExtractor={keyExtractor}
listKey={listKey}
legacyImplementation={false}
numColumns={1}
renderItem={this.renderItem}
initialNumToRender={MAX_POSTS_TO_RETRIEVE_LENGTH} // 10
windowSize={32}
maxToRenderPerBatch={15}
updateCellsBatchingPeriod={50}
removeClippedSubviews={false}
ListFooterComponent={this.renderFooter}
ListEmptyComponent={ListEmptyComponent}
onEndReached={onEndReached}
onEndReachedThreshold={0.5}
/>
有任何想法嗎? 我已經看到這是一個常見問題,但我還沒有找到任何解決方案。
要解決我使用 getItemLayout 遇到的問題,請執行以下操作:
getItemLayout = (data, index) => {
const length = this.itemHeights[index] || 0; // <----- if undefined return 0
const offset = this.itemHeights.slice(0,index).reduce((a, c) => a + c, 0)
return {length, offset, index}
}
如果有人遇到這種情況,請使用我的自定義 getItemLayout 函數並按照以下步驟操作
使用這些價值觀對我有用。
initialNumToRender={10}
windowSize={5}
maxToRenderPerBatch={5}
updateCellsBatchingPeriod={30}
removeClippedSubviews={false}
...
onEndReachedThreshold={0.1}
Pd:我的視口被 1.5 個項目覆蓋
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.