Flat List - ScrollToIndex should be used in conjunction with getItemLayout or onScrollToIndexFailed

Viewed 22521
setTimeout(() => { this.myFlatList.scrollToIndex({animated:true , index: 100}) }, 100);  

enter image description here

If i use scrolltoindex in flat list return to me this error;

scrollToIndex should be used in conjunction with getItemLayout or onScrollToIndexFailed

I tried to use getItemLayout but my flatlist items have different height, how can i fix this?

getItemLayout={(data, index) => (
                {length: 40, offset: 40 * index, index}
              )}
3 Answers

I had a similar error with a horizontal list showing images where the selected image should be shown in a carousel when pressed.

I solved it by setting the selected index on the FlatList by using initialScrollIndex. I also used onScrollToIndexFailed to scroll to the correct image for the times when initialScrollIndex failed to show the correct image.

This is done by setting a timeout for 500ms and then scroll to the selected image.

Complete example (with only the props regarding this error):

const flatList = useRef<FlatList>(null);

...

<FlatList
  ref={flatList}
  initialScrollIndex={props.activeIndex}  
  onScrollToIndexFailed={info => {
    const wait = new Promise(resolve => setTimeout(resolve, 500));
    wait.then(() => {
      flatList.current?.scrollToIndex({ index: info.index, animated: true });
    });
  }}
/>

I had a similar problem and solved it by changing initialNumToRender in FlatList.

This prop defines how many components to render. If you scroll to an index which has not been rendered, then the error will show.

React Native initialNumToRender default is 10, I changed for initialNumToRender={60}. You need to change this number if your list is bigger or smaller.

The proposed solution wasn't working in my case.

My understanding is that the FlatList lays out only a few next items in the list (initialNumToRender) and can scroll only to those items, but not beyond.

If the list items all have same height, I have another solution that works even on long lists. That is to scroll to a specific coordinates instead:

export default MyComponent = props => {
  const flatListRef = useRef()

  return (
    <FlatList
      ref={flatListRef}
      ...
      onScrollToIndexFailed={({
        index,
        averageItemLength,
      }) => {
        // Layout doesn't know the exact location of the requested element.
        // Falling back to calculating the destination manually
        flatListRef.current?.scrollToOffset({
          offset: index * averageItemLength,
          animated: true,
        });
      }}
    />
  );
};
Related