admin管理员组

文章数量:1316351

Introduction

I am having serious performance issues with my VirtualizedList (infinite scroll)... I have been following this to improve it but still working really slow.

When I scroll down, the UI threads go from 60fps to 30fps, and the JS thread from 60fps to 10/20fps (sometimes to 0fps). On iOS (iPhone 6) it seems to go smoothy than on my Android (Samsung Galaxy S8+)

My VirtualizedList is rendering items with different heights, and it fetches the data when its end is reached. My item extends from React.PureComponent, as it is remended:

VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders ponents that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. Object { "contentLength": 20720, "dt": 532, "prevDt": 2933, }

This issue es when I scroll down around 20 items...

Code

Here is the code of the VirtualizedList:

const keyExtractor = ({ id }) => id;
...
 
getItem = (data, index) => data[index];

getItemCount = (data) => data.length;

renderItem = ({ item, index }) => {
 const {
   images,
   dimensions,
   description,
   location,
   likes,
   ments,
   date,
 } = item;

 return (
   <Card
     images={images}
     postDimensions={dimensions}
     description={description}
     location={location}
     likes={likes}
     ments={ments}
     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: each item I am rendering has an unique id.

What I have tried

I have tried to implement my own getItemLayout method for the List but for some reason it doesn't work properly.

Warning: Failed frame type: The frame frame.length is marked as required in VirtualizedList.getItemLayout, but its value is 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,
   ments,
   date,
 } = item;

 return (
   <View onLayout={(event) => this.itemHeights[index] = event.nativeEvent.layout.height}>
    <Card
      images={images}
      postDimensions={dimensions}
      description={description}
      location={location}
      likes={likes}
      ments={ments}
      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}
/>

Any ideas? I have seen that it is a mon problem but I haven't found any solution.

UPDATE

To solve the issue I was getting with getItemLayout just do:

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}
}

Introduction

I am having serious performance issues with my VirtualizedList (infinite scroll)... I have been following this to improve it but still working really slow.

When I scroll down, the UI threads go from 60fps to 30fps, and the JS thread from 60fps to 10/20fps (sometimes to 0fps). On iOS (iPhone 6) it seems to go smoothy than on my Android (Samsung Galaxy S8+)

My VirtualizedList is rendering items with different heights, and it fetches the data when its end is reached. My item extends from React.PureComponent, as it is remended:

VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders ponents that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. Object { "contentLength": 20720, "dt": 532, "prevDt": 2933, }

This issue es when I scroll down around 20 items...

Code

Here is the code of the VirtualizedList:

const keyExtractor = ({ id }) => id;
...
 
getItem = (data, index) => data[index];

getItemCount = (data) => data.length;

renderItem = ({ item, index }) => {
 const {
   images,
   dimensions,
   description,
   location,
   likes,
   ments,
   date,
 } = item;

 return (
   <Card
     images={images}
     postDimensions={dimensions}
     description={description}
     location={location}
     likes={likes}
     ments={ments}
     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: each item I am rendering has an unique id.

What I have tried

I have tried to implement my own getItemLayout method for the List but for some reason it doesn't work properly.

Warning: Failed frame type: The frame frame.length is marked as required in VirtualizedList.getItemLayout, but its value is 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,
   ments,
   date,
 } = item;

 return (
   <View onLayout={(event) => this.itemHeights[index] = event.nativeEvent.layout.height}>
    <Card
      images={images}
      postDimensions={dimensions}
      description={description}
      location={location}
      likes={likes}
      ments={ments}
      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}
/>

Any ideas? I have seen that it is a mon problem but I haven't found any solution.

UPDATE

To solve the issue I was getting with getItemLayout just do:

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}
}
Share Improve this question edited Sep 13, 2020 at 9:36 Victor Molina asked Sep 13, 2020 at 8:26 Victor MolinaVictor Molina 2,6613 gold badges28 silver badges59 bronze badges 9
  • Try to ment the images and see if that is cause of the slow rendering. It will not your problem but you will know what the source of the problem is. – D10S Commented Sep 13, 2020 at 9:05
  • What do you mean by ment the images? Replacing/menting the Card ponent with an other?? – Victor Molina Commented Sep 13, 2020 at 9:11
  • 1 Not the whole Card ponent but only the <Image>'s tag. This way you will have the list without images. If the performance improves you'll know its the images causing the problem – D10S Commented Sep 13, 2020 at 9:17
  • Yes, it seems that the problem is with the images... When I removed this tag, the UI thread minmum value was 50fps when scrolling, and the JS thread 50fps too. I have also appreciated that the image causes the item to be removed when it goes ouside the viewport... Maybe this is because I am getting the images from my device cache (I cached them when they are rendered)... – Victor Molina Commented Sep 13, 2020 at 9:33
  • 1 I'm Glad for you. Thank you for updating. – D10S Commented Sep 14, 2020 at 6:16
 |  Show 4 more ments

1 Answer 1

Reset to default 7

If this happen to someone, just use my custom getItemLayout function and follow these steps

Using those values has worked for me.

    initialNumToRender={10}
    windowSize={5}
    maxToRenderPerBatch={5}
    updateCellsBatchingPeriod={30}
    removeClippedSubviews={false}
    ...
    onEndReachedThreshold={0.1}

Pd: my viewport is covered with 1.5 items

本文标签: javascriptReact NativeVirtualizedList You have a large list that is slow to updateStack Overflow