react-native: Performance issue with large data: Cells/Rows in the loading slowly on Android

TL;DR

With large data, SectionList will:

  1. reload the same item repeatedly
  2. performance issue on Android (laggy and only update a few item per scrolling)

Is this a bug report?

YES

Have you read the Bugs section of the Contributing to React Native Guide?

YES

Environment

  1. react-native -v: 0.45.1 & 0.46.1 (I’ve tried both versions)

  2. node -v: v7.8.0

  3. npm -v: 4.2.0

  4. yarn --version (if you use Yarn): 0.22.0

  5. Target Platform (e.g. iOS, Android): Android

  6. Development Operating System (e.g. macOS Sierra, Windows 10): macOS

  7. Build tools (Xcode or Android Studio version, iOS or Android SDK version, if relevant): Android SDK 25.0.2

Steps to Reproduce

  1. I have a LoginCountryList component to display a SectionList:
export default class LoginCountryList extends React.Component {

  props: LoginCountryListProps;
  static defaultProps = {
    data: {},
  };

  renderRow = (rowItem: any) => {
    console.log('render row:');
    return (
      <TouchableHighlight
        onPress={() => this.props.onSelectRow(rowItem.item)}
      >
        <View style={styles.row}>
          <Text style={styles.rowLeftText}>{rowItem.item.name}</Text>
          <Text style={styles.rowRightText}>{`+${rowItem.item.ccc}`}</Text>
        </View>
      </TouchableHighlight>
    )
  };

  renderSectionHeader = (sectionItem: any) => (
    <View
      style={styles.sectionHeader}
    >
      <Text style={styles.sectionHeaderText}>{sectionItem.section.title}</Text>
    </View>
  );

  render() {

    console.log('re-render section list')
    return (
        <SectionList
          style={styles.listView}
          sections={this.props.data}
          renderItem={this.renderRow}
          renderSectionHeader={this.renderSectionHeader}
        />
    );
  }
}

// data:

const data = [
  // first section
  {
    "title": "A",
    "key": "A",
    "data": [
      // first row
      {
        "ccc": "93",
        "countryCode": "AF",
        "currencyCode": "AFN",
        "currencySymbol": "؋",
        "name": "Afghanistan",
        "key": "AF"
      },
      {
        "ccc": "355",
        "countryCode": "AL",
        "currencyCode": "ALL",
        "currencySymbol": "Lek",
        "name": "Albania",
        "key": "AL"
      },
      ...
    ]
  },
  ...
]

// Use 
<LoginCountryList data={data}/>
  1. Running on Android devices
  2. Encounter problems (see below)

Expected Behavior

  1. Scroll smoothly as running on iOS devices.
  2. The same items do not render multiple times.

Actual Behavior

  1. Only render a few new rows/cells per scrolling, not smoothly.
  2. The method renderRow would be called multiple times for the same row when mounting.

Explanation

I use the new API <SectionList/> to build a list UI, but I found issues running on Android devices.

  1. While scrolling down with SectionList, only a few new cells/rows can be displayed at once. You need to scroll SectionList down again to display the next a few new cells/rows, and wait for the next cells are ready to be displayed. It works not the same on the iOS.
  2. When reaching the last item in the SectionList, I tried to scroll up quickly to the first item in the SectionList, and it display a blank view with a few seconds till the cells are rendered.

I have hundred rows (country list) for display, and the user experience is bad. The user takes many seconds to reach the last item in the country list, and takes many seconds to show the previous rows after scrolling up quickly.

I tried to log in the renderItem callback when SectionList did display, and it calls renderItem hundred times for displaying only 15 rows in the first section.

Log a constant string render row: with hundred times when the SectionList did display:

screen shot 2017-07-12 at 17 07 46

Log the indexes of the items when the SectionList did display. The same row did render multiple times when the SectionList did display.

screen shot 2017-07-12 at 17 10 21

Did use SectionList wrongly? How do I do to fix it?

Reproducible Demo

https://github.com/xareelee/SectionListSlowRenderingOnAndroid

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 33 (3 by maintainers)

Commits related to this issue

Most upvoted comments

This issue looks like a question that would be best asked on StackOverflow.

StackOverflow is amazing for Q&A: it has a reputation system, voting, the ability to mark a question as answered. Because of the reputation system it is likely the community will see and answer your question there. This also helps us use the GitHub bug tracker for bugs only.

Will close this as this is really a question that should be asked on StackOverflow.

mybe you can try this: https://github.com/bolan9999/react-native-largelist

if it is useful for you, star me,please

I have this issue as well. When using <SectionList> with two arrays it is incredibly slow but with one <FlatList> for each array it is rendering instantly.

<SectionList
	sections={[
		{
			data: this.props.favorites,
			renderItem: this.renderDepartures
		},
		{
			data: this.props.departures,
			renderItem: this.renderDepartures,
			title: 'departures'
		}
	]}
	keyExtractor={item => item.journeyid}
	ItemSeparatorComponent={ListItemSeparator}
	renderSectionFooter={this.renderSectionFooter}
	getItemLayout={(data, index) => (
		{ length: 51, offset: 51 * index, index }
	)}
	maxToRenderPerBatch={11}
	initialNumToRender={11}
/>
<FlatList
	data={this.props.favorites}
	renderItem={this.renderDepartures}
	keyExtractor={item => item.journeyid}
	ItemSeparatorComponent={ListItemSeparator}
	ListFooterComponent={this.ListFooterComponent}
	getItemLayout={(data, index) => (
		{ length: 51, offset: 51 * index, index }
	)}
	maxToRenderPerBatch={11}
	initialNumToRender={11}
	scrollEnabled={false}
/>
<FlatList
	data={this.props.departures}
	renderItem={this.renderDepartures}
	title={'departures'}
	keyExtractor={item => item.journeyid}
	ItemSeparatorComponent={ListItemSeparator}
	getItemLayout={(data, index) => (
		{ length: 51, offset: 51 * index, index }
	)}
	maxToRenderPerBatch={11}
	initialNumToRender={11}
	scrollEnabled={false}
/>

RN 0.56 has this bug. FLatList and SectionList backend is Scrollview on android, I think this is the key for this bug. When I scroll up and down, item was travel every time, even though it was travel before. image

Simple item

class MyListItem extends React.PureComponent {
    _onPress = () => {
        this.props.onPressItem(this.props.id);
    };

    render() {
        const textColor = this.props.selected ? "red" : "black";
        return (
            <TouchableOpacity onPress={this._onPress}>
                <View style={{paddingLeft:10, height: ITEM_HEIGHT}}>
                    <Text style={{ color: textColor }}>
                        {this.props.title}
                    </Text>
                </View>
            </TouchableOpacity>
        );
    }
}

@RoarRain were you able to solve this? Can you please guide me too? I’m already using PureComponent and getItemLayout. How should I use shouldComponentUpdate in this regard?