iOS
reactnative

How to build an "infinite" list in ReactNative

More than 1 year has passed since last update.

Hello, I'm an iOS engineer working at Retty, Inc.
In the last few months, we have re-created our iOS application with Swift & ReactNative.
And we have decided to create the list of user's posts with ReactNative.

Lists in ReactNative

When talking about a list in ReactNative, we have three different choices.
1. ListView
2. FlatList & SectionList
3. Third-party libraries (e.g. recyclerlistview)

FlatList & SectionList

As FlatList & SectionList is recommended by the official site of ReactNative, and because I want to show some section headers on my list, I tried SectionList first.
It has a very nice interface, and you can build a list with section headers, RefreshControl and infinite scroll without any effort.

      <SectionList
        style={styles.list}
        sections={sections}
        extraData={this.state}
        keyExtractor={this.keyExtractor}
        renderSectionHeader={this.renderSectionHeader}
        renderItem={this.renderItem}
        enableEmptySections
        legacyImplementation
        stickySectionHeadersEnabled
        refreshing={false}
        onRefresh={this.onRefresh}
        onEndReached={this.onEndReached}
      />

Just that, you can build a very "nice" list.
But the problem comes now, I found sometimes there are blank cells showing up when scrolling the list, with a very quick scroll, there will be lots of blank cells.
It's so weird, as an answer, I found that

Different from ListView, in order to resolve the memory issue of ListView, FlatList & SectionList are built based on a virtualized listview.
The virtualized listview unmounts views that have gone out of the viewport, and it relies on ScrollView to do its layout and appropriately replaces unmounted views with blank views.

Okay, here is the reason why I can see blank cells when scrolling.

ListView

After lots of research on how to improve SectionList (actually there is not so much information about it), I decided to give it up, and give ListView a try.
In the latest version of ReactNative, ListView has already been DEPRECATED.
The reason is ListView has a memory issue when building a large list. I don't know what's the definition of "large list" here, so I decided to have a try.
Actually ListView has almost the same interface and functionalities comparing with SectionList.

      <ListView
        style={styles.list}
        dataSource={this.state.dataSource}
        renderSectionHeader={this.renderSectionHeader}
        renderRow={this.renderRow}
        enableEmptySections
        stickySectionHeadersEnabled
        refreshControl={
          <RefreshControl
            refreshing={false}
            onRefresh={this.onRefresh}
          />
        }
        onEndReached={this.onEndReached}
      />

That's it, not many changes.
I tested it with my account, ListView works very fine, even it's difficult to find the difference between ListView and ListViews of pure native implementation.
At this point, I didn't know why ListView has been deprecated, it works absolutely better than "new" SectionList.
And we released the ListView version to Apple store.
After a couple of days, I got several crash reports of this part. From the crash report, I found it crashes when displaying a user's post list with over 4,000 posts, and the reason is memory issue.
By checking Xcode's memory graph, I realized that when I scroll down the list, the memory usage keeps growing. It reaches 500 MG after scrolling to over 500 posts, it's very very bad performance. And after scrolling to over 500 posts, the application crashes on an iPhone6.
Now, I know what is the "memory issue" of ListView talking about.
After reading some source code of ListView's implementation, I got the answer

  1. ListView doesn't reuse cells.
  2. There is also no virtualization of any kind, leading to huge increase in memory usage as you scroll down a practically infinite list.
  3. There is one more problem is that listview listens to scroll event and renders items as you scroll down, this is great but it also means if you scroll too quickly the scroll would come to halt before items are rendered.

Oops, I shouldn't put it into production at all.

Third-party libraries

There are tons of third-party libraries, but most of them are built based on ListView or FlatList & SectionList, means that no one is really resolving those problems.
There are also some libraries like recyclerlistview, they have their own implementation of the listview, but most of them have the almost same concept of the virtualized listview, which also has the same problems remaining not resolved.

Conclusion

As a very positive supporter of ReactNative, I don't like to but I have to draw a conclusion, that

It's not possible to build a large list in ReactNative!

I really hope someone can overthrow my conclusion, but now I have to decide to re-implement all the stuff in pure native.