0
votes

I have a Flatlist. The data array is the contents of a book(paragraphs, images, subHeadings). How do I implement the getItemLayout prop correctly on my FlatList? I understand this is suppose to tell the FlatList the height of each item to make it more performant. However how am I to find out the size of each item? Is that something that I am to determine arbitrarily meaning by guesstimating? Every item is a different size. I have tried entering random values in getItemLayout just to see what happens however I don't really know how to tell which value would be the correct value.

This is my FlatList

 <FlatList
      ref={flatListRef}
      contentContainerStyle={{ paddingHorizontal: 10 }}
      showsVerticalScrollIndicator={true}
      initialNumToRender={10}
      data={dataRef}
      renderItem={renderItem}
      onScrollToIndexFailed={scrollFailToIndex}
      getItemLayout={(data, index) => {
        return { length: 0, offset: 0 * index, index };
      }}
    />

This is a piece of my data array...

const dataRef = [
  {
    img: "tr1Cover",
    id: "1Tr 1.cover",
    key: "0",
  },
  {
    text: "Copyright 1933,1940,1941\nAll rights reserved\nV. T. HOUTEFF.",
    style: "plainCenterText",
    key: "1",
  },
  {
    text:
      "In the interest of reaching every truth-seeking mind that desires to escape the path that leads to destruction of both body and soul, this tract will be distributed free of charge as long as this issue lasts.",
    id: "1Tr 2.1",
    style: "plainText",
    key: "2",
  },
  {
    text: "PREFACE PERSONALLY WATCHING FOR EVERY RAY OF LIGHT.",
    style: "subHeading",
    key: "3",
  },
  {
    text:
      "One who entrusts to another the investigation of a message from the Lord, is making flesh his arm, and thus is foolishly acting as without a mind of his own. And  ”the mind that depends upon the judgment of others is certain, sooner or later, to be misled. ” -- Education, p. 231.",
    id: "1Tr 3.1",
    style: "plainText",
    key: "4",
  },

This is my renderItem function...

  const renderItem = useCallback(({ item }) => <ListItem item={item}></ListItem>, []);

This is my ListItem Component...

class ListItem extends PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    if (this.props.item.img) {
      return (
        <Image
          source={Images[this.props.item.img]}
          resizeMode="stretch"
          style={{
            alignSelf: "center",
          }}
        />
      );
    }
    if (this.props.item.text) {
      return (
        <Text selectable={true} style={styles[this.props.item.style]}>
          {this.props.item.text}
          <Text style={styles.pagination}>{this.props.item.id}</Text>
        </Text>
      );
    }
  }
}

From time to time I get this warning...

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

I was told it's because I am not using the getItemLayout prop. I also notice the scrolling is a bit glitchy/laggy at times. I was aiming to do my project without class components however I heard using PureComponents was a recommendation for performant flatLists and so I made one thinking it would solve my lag problem.

Just showing what the content looks like for clarity...

enter image description here

1

1 Answers

0
votes

If your list items consistently have the same height, you can pass it to that prop to prevent React Native from having to measure them every time. Even if you are not explicitly setting the height as a style, the computed height may be the same. You can find this by inspecting your items in dev tools.

Most likely, though, the performance issues are the result of a number of factors. How large are the images that you're rendering? Are they significantly larger than the rendered dimensions, and could they be resized? How many items are you rendering?

Also, try removing the useCallback on your renderItem. That may actually worsen performance here, and is unnecessary