jsoendermann/rn-section-list-get-item-layout

Tries to access out of bounds section

Closed this issue · 8 comments

An error is thrown on this line: https://github.com/jsoendermann/rn-section-list-get-item-layout/blob/master/index.ts#L18.

It tries to access a section with index 8, while the last section index is 7. This causes a "Cannot read property 'data' of undefined" error.

Very strange, it seems that getItemLayout sometimes gets called with an index that seems out of bounds. I've set up an example with 2 sections, containing 1 row each. The getItemLayout prop is called multiple times with indexes ranging from 0 to 5. I would think that the max index should be 3...

Hey, thanks for opening an issue. Could you send me the code that causes this so that I can take a look?

I've opened an issue about this on the react-native repo: facebook/react-native#14972. Although, I'm not sure whether it's a problem with React Native or rn-section-list-get-item-layout.

I tried to create an Expo Snack that shows the problem, but couldn't reproduce it there. I'll see if I can whip up a quick example project locally.

If you drop this into a fresh React Native project, you'll see what happens:

import React, { Component } from 'react';
import { AppRegistry, StyleSheet, View, Text, SectionList, PixelRatio } from 'react-native';
import sectionListGetItemLayout from 'react-native-section-list-get-item-layout';

export default class GetItemLayoutDemo extends Component {

  constructor(props) {
    super(props);

    // This crashes

    // this.getItemLayout = sectionListGetItemLayout(
    //   () => 40,
    //   () => 1 / PixelRatio.get(),
    //   (rowData, sectionIndex, rowIndex) => 40
    // );


    // This works

    this.getItemLayout = (data, index) => {
      console.log(`getItemLayout called with index: ${index}`);
      return { length: 40, offset: 40 * index, index: index };
    };
  }

  render() {
    const sections = [
      {
        key: 'section1',
        data: ['Row']
      },{
        key: 'section2',
        data: ['Row']
      }
    ];

    return (
      <SectionList
        sections={sections}
        keyExtractor={(item, index) => index}
        ItemSeparatorComponent={() => {
          return <View style={{height: 1, backgroundColor: 'red'}} />
        }}
        renderSectionHeader={() => {
          return <Text style={{height: 40, backgroundColor: 'green'}}>Section header</Text>
        }}
        renderItem={() => {
          return <Text style={{height: 40, backgroundColor: 'yellow'}}>Row</Text>
        }}
        getItemLayout={this.getItemLayout}
      />
    );
  }
}

AppRegistry.registerComponent('GetItemLayoutDemo', () => GetItemLayoutDemo);

Getting the same problem:

Cannot read property 'data' of undefined

The sectionIndex is out of bounds of the array (1 too big).

Ok, after digging through the react native sources it seems that we have to account for section footers even when using SectionList without a renderSectionFooter prop. For some reason, it doesn't call getItemLayout for section headers which is why the indices we get with @wvteijlingen's code are 1 2 4 and 5 (0 and 3 are the two section headers).

I'll push something before dinner.

I just pushed version 2.0.0 (sectionListGetItemLayout's parameters have changed). Let me know if you try it.

Thanks for the quick response, it looks very nice! It seems to work great for me. 👍 You'd really think FlatList and SectionList would include such functionality...