React-native: [FlatList] FlatList and VirtualizedList Scroll performance is laggy after 30+ rows .

Created on 10 Apr 2017  ยท  118Comments  ยท  Source: facebook/react-native

Description

Flatlist or VirtualizedList Scroll lags horribly after 30-40 rows . I am fetching the same data on onEndReached . Upto 30 rows its looks fine , but after that scrolling drops several frames . When I disable virtualization , scroll becomes normal but but responsiveness goes away . I tried disabling virtualizing on scrolling velocity this way .

  isVirtualizationTrue(e){
  var dOffset=(e.nativeEvent.contentOffset.y- this.state.lastOffset)
  var dt=(e.timeStamp-this.state.lastTimeStamp) 
  var velocity = dOffset/dt

  var isInstant=velocity-this.state.lastVelocity>.01


  if(velocity<1 && !isInstant){

      return false
  }
  if(velocity>1){
      return true
  }
  if(velocity <.25){
      return  true
  }

}
But again , there's problem for the unmounted Component that are removed from the views , which takes long time to show up again .

Is there any way to improve the scroll performance ?

Here's my sample code

  <FlatList

    shouldItemUpdate={(props,nextProps)=>
       { 
         return props.item!==nextProps.item

}  }



   onEndReached={this.onRefresh.bind(this)}
   onEndReachedThreshold={200}


    onRefresh={this.onRefresh.bind(this)}
    refreshing={this.props.Feed.isFetching }
    data={this.state.items} 
    renderItem={this.renderItem.bind(this)}  />

My data is sort of large and nested object by the way .
And data contains High quality Images . Per row there's two Items . But I implemented it without using numColums for testing with Virtualizedlist instead of Flatlist , but same result . Is it due to the High quality Image or I am doing something wrong ?

Additional Information

  • React Native version: 0.43.2
  • Platform: Android
  • Development Operating System: Windows 10
Bug FlatList

Most helpful comment

I had similar performance issues with FlatList and here's what I did to solve it:

  1. Make sure FlatList is not a child of ScrollView as scrollview will render all child components, even those not on the screen in FlatList.
  2. Add prop removeClippedSubviews to FlastList so it removes items out of view. (didn't test if this is redundant to #1)
  3. Implement shouldComponentUpdate for the renderItem component or make it a PureComponent.

All 118 comments

Its most likely due to the nested components as you mentioned (nothing to do with HQ images).
I've had a similar issue, right now I am not providing a shouldItemUpdate method, and instead deailing with shouldComponentUpdate for each of my nested components in the list. Its more work but its helped with the responsiveness. Its still not perfect though so I'd like to hear what others say as well.
When I switched to that pattern I also ended up getting the dreaded:

VirtualizedList: You have a large list that is slow to update - make sure shouldItemUpdate is implemented effectively and consider getItemLayout, PureComponent, etc. 

statement again, but when shouldItemUpdate is provided I don't see that message even though the list is less responsive.

@jpshelley hey man , Thanks for the idea . Actually you saved me , but in an another way . I only upgraded to 0.43 just for VirtualizedList thinking it would have great performance . But it turned out it's not mature enough and lots of bugs to be fixed yet . Scrolling was quicker (i mean it fetches data before the onEndReach) but laggy (i mean shaky) . Implenting shouldComponentUpdate makes the scroll performance more horrible (but responsiveness got fixed) .
I thought Listview had horrible performance as I didn't implented the shouldComponentUpdate in rederRow. But today I again tried ListView with shouldComponentUpdate and it was great . I am going for ListView again . 0.43 has lots of issues , navigator performance is not good as 0.41 .
Anyway waiting for the WindowedList which is as experimental. Hope it fixes all problems.

I'll add one more piece of information that might be relevant for a fix:

When I was investigating the issue mentioned above, I spent a lot of time pulling out pieces of code that could cause unnecessary updates. Additionally, I implemented shouldItemUpdate so that I could understand what was causing the FlatList to re-render its items so often. That's when I noticed something peculiar. Once you get past about the first 30 items, shouldItemUpdate gets called a ridiculous number of times event though there is no diff between new and old item props for either the items or the FlatList. In my case, I was seeing a print statement embedded in shouldItemUpdate (no, the print wasn't causing the lag) written to console nearly _1000 times_ for a single slow scroll.

The only way to prevent the jumpy scrolling behavior was to set disableVirtualization to false.

@SunburtReynolds Hey , you are absolutely right . And there's also an another issue with the new the updated version of Flatlist , which have separated the Fillrate function . The Fillrate logic was not performing good and it causes shakiness during scroll as is preassumed height was not equal to the height after rendering . Lots of bugs has to be fixed . So I downgraded to listview again . You can achieve a similer kind of smooth scroll in listview using dynamic onEndReachedThreshold . Suppose for a datasource of length N , you can set the threshold as n*N where n is a constant floating point and N is dynamic length.

We need to be able to control the viewabilityThreshold offered by the FlatList. Otherwise we would most likely revert to ListView as well.

I have the same issue, but got it solved ๐Ÿ˜ƒ
Just made a fix for it. I solved it by clearing all items that are not in the viewport to free memory and CPU usage.

see more of the fix here:
https://github.com/stoffern/react-native-optimized-flatlist
๐Ÿ˜‰

@stoffern I'm already replicating this behavior with my code base using FlatList, as I'm rendering lots of images / videos. But unfortunately with Android FlatList behaves entirely differently and keeping the viewableItems in state doesn't work. The initial rendering renders all the items in the list. Have you run into this with your library?

@gp3gp3gp3 try my library and see if it works.
I had the issue you describe and it works fine for me after i use the OptimizedFlatList

I dont keep them in the state as that would cause the FlatList to do a full re-render everytime a item changed. Look at my code and see if that makes more sense ๐Ÿ˜‰

Tried different ways and methods with Flatlist; spent 2 days experimenting with it, but its not prime time if you are looking to render pics and videos in a list. ListView still works smoothly.

Add the following props in your Flatlist its work
onEndReachedThreshold={1200}

Doesn't that basically turn the FlatList into a ListView though?

FWIW, version 0.45.1 seems to have fixed the jumpy scrolling issue!

Wrapping the whole Flatlist in a ScrollView worked for me.

@stoffern have tried your lib and it doesn't help.
I have to switch back to ListView after all.

is there a fix yet?

I remember when I started this project at 0.29... feels like Ive been chasing the magic dragon updating every minor version. +1 for listview

I changed my render item component into PureComponent and it works fine

+1

We've had lot of problems with react native listview as well so, we built one ourselves, just open sourced it. We've tested it with 5000 items works like a charm. The reason it's so fast is that it uses a quick staggered grid algorithm and recycles views (based on types) instead of destroying them once they're out of view port. Please try it out and give us feedback https://www.npmjs.com/package/recyclerlistview

Hei @naqvitalha , Its really good to know that you have created an recyclerview library . I was always looking for that . However ,it was for an another reason , I needed a component to build snapped scrollviews like google-play-store apps scroll . React-native currently lacks that library . I wonder why nobody has created one yet . Please let me know if you can add that functionality with snaphelper , I believe it's possible only using recyclerview . Here re some links you can have a look .

https://rubensousa.github.io/2016/08/recyclerviewsnap

https://blog.mindorks.com/using-snaphelper-in-recyclerview-fc616b6833e8

@PARAGJYOTI The listview that I talked about is not based on native recycler view, it's written from scratch purely in JS, making it cross platform (also web :) ). You can open an issue. We can certainly add this in the future.

@naqvitalha Owh , I thought it was native . Anyway , is flipkart also using react-native for mobile ?

@PARAGJYOTI Yes we are.

I don't know why, but try legacyImplementation, it does the trick

+1 have the same performance problem

So am I ๐Ÿ˜ข

Then why don't you guys give RecyclerListView a chance? https://www.npmjs.com/package/recyclerlistview

@naqvitalha In recyclerlistView why need ViewTypes , I not really got it

ViewTypes are needed to efficiently recycle cells. So that similar looking cells are recycled. You can just return one type in layout provider in case you don't need it.

I have a horizontal list and I see some delay when I call scrollToIndex. It gets really slow with 20-30 elements.

I had similar performance issues with FlatList and here's what I did to solve it:

  1. Make sure FlatList is not a child of ScrollView as scrollview will render all child components, even those not on the screen in FlatList.
  2. Add prop removeClippedSubviews to FlastList so it removes items out of view. (didn't test if this is redundant to #1)
  3. Implement shouldComponentUpdate for the renderItem component or make it a PureComponent.

@justinlok does #1 proven already? Is it bad for a listview/flatlist inside a scrollview?

@gitlovenotwar when i had flatlist within a scrollview, i noticed all flatlist items were being rendered at once. I realize now that the docs say to define a height for scrollview which i dont think i did. That may have been the reason all items were rendered at once.

Anyways, i do not see a reason to use scrollview instead of a simple view. Flatlist still scrolls fine within a view. If somebody can explain it would be great.

I ended up rolling back to listview for some screens .. flatlist is still super random :(

You can try utilising legacyImplementation, via legacyImplementation?: ?boolean prop. Set it to true.

In my case, our x-hundred lines long list with pretty complex item components, which felt really clunky, suddenly became super-fast. ๐Ÿค” โ“

There probably are some caveats/limitations to legacyImplementation. In my case, it does the trick though.

Can someone confirm/displace this?

@jankoritak Legacy implementation is plain old ListView. It generally works better but it has a disadvantage of poor performance.

@mannol actually old ListView's performance is better. Problem there is the lack of virtualization which increases memory usage.

@naqvitalha yes, though increased memory usage has a major performance impact on Android. In my observations, legacy implementation behaves the same way as ListView: no virtualisation, so, there is no clear benefit of using FlatList in that case, except for the cleaner API.

@naqvitalha What is that recycleviewlist good for?

In our case we need an infinite list basically. (Making a calendar)

@SudoPlz Check this out https://github.com/naqvitalha/CalenderDemo I actually did something like that. But the project is incomplete (perf wise), issues are listed in the readme. New versions of RecyclerListView has changes which can make this much faster but haven't had the time to update. Btw RecyclerListView is much faster alternative to FlatList with context preservation.
Check the app if you want (you can scroll the date list too): https://drive.google.com/open?id=0B90JDy5HZpFxOEpPVmtjaHZkX3M

FlatList and SectionList is bad performance. Try this,please. may be it is a surprise for you

https://github.com/bolan9999/react-native-largelist

Hi Guys,
I was facing same issue, while experimenting following setting has solved my problem, Hope this will also help others.

Set removeClippedSubviews and disableVirtualization for Flatlist and it will work like charm.

<FlatList removeClippedSubviews disableVirtualization ... />

package.json :
"react-native": "0.51.0",

@bamne123 it still happens.

@mymai91 can you share your code?

hi thanks, but It's fixed.
I use the way approach from jpshelley

@bamne123 disableVirtualization is basically translate your code into listview. Why bother using flatlist?

Hey all, quick followup on this issue (since it has been reported a couple more times). It seems like this combination of Android + Flat/SectionList + Images can lead to sub-optimal performances, and the core team is aware of it.

While the issue is investigated, here are few things you may want to try for a FIY solution:

  1. go back and read this comment
  2. go back and read this other comment
  3. make sure you are using the full-range of props to tweaks the params of the Flat/SectionList (remember that they inherit from VirtualizedList and ScrollView) (I personally suggest to enable removeClippedSubviews only on Android)
  4. consider optimising your Fresco configuration

Hope this may help!

@jankoritak @blackmiaool legacyImplementation is the trick too :) and now my app become flying

Going to +1 for legacyImplementation, too. I can't use that, though, as it does not support my header, so I've instead resorted to removeClippedSubviews={Platform.OS === 'android'} as suggested by @kelset for now. It is not as performant as legacyImplementation, but it's better than the default false setting. FWIW, I'm using PureComponent for my rows, and they are all of the same type in a Facebook/Instagram like feed with images, comments and profile pictures.

Anxiously awaiting resolution of this issue, as infinite scrolling feeds with images are the main feature of two of my production apps :-)

Hi guys,

I have not found an example of how to use PureComponent in my renderItem component. Currently, I'm using an arrow function. Can you give some tips?

What I have tried:

class Item extends React.PureComponent {
    render() {
        return <Text>Hello world</Text>;
    }
}
<SectionList
    refreshing={refreshing || fetchingNext}
    onRefresh={(() => { })}
    stickySectionHeadersEnabled={true}
    sections={this.transformSectionsData(documents)}
    renderSectionHeader={SectionHeader}
    renderItem={Item}
    keyExtractor={this.keyExtractor}
    onEndReached={this.fetchNextPage}
/>

image

You can fix the issue by retrieving the data to Flatlist using the pagination technique in you backend. Please refer this video https://www.youtube.com/watch?v=rY0braBBlgw

@shanakaf that's not the problem here.

got excited about legacyImplementation but getting the error:

TypeError: Requested keys of a value that is not an object.

This error is located at:
in MetroListView (at FlatList.js:632)
in FlatList (at NotificationScreen.js:97)
in RCTView (at View.js:78)
in View (at NotificationScreen.js:92)
in Screen (created by Connect(Screen))
in Connect(Screen) (at SceneView.js:17)
in SceneView (at ResourceSavingSceneView.js:55)
in RCTView (at View.js:78)
in View (at ResourceSavingSceneView.js:48)
in RCTView (at View.js:78)
in View (at ResourceSavingSceneView.js:39)
in ResourceSavingSceneView (at TabView.js:35)
in RCTView (at View.js:78)
in View (created by ViewPagerAndroid)
in AndroidViewPager (at ViewPagerAndroid.android.js:238)
in ViewPagerAndroid (at TabViewPagerAndroid.js:127)
in TabViewPagerAndroid (at TabViewAnimated.js:71)
in RCTView (at View.js:78)
in View (at TabViewAnimated.js:194)
in TabViewAnimated (at TabView.js:192)
in TabView (at withCachedChildNavigation.js:69)
in withCachedChildNavigation(TabView) (at TabNavigator.js:34)
in Unknown (at createNavigator.js:13)
in Navigator (at createNavigationContainer.js:226)
in NavigationContainer (at SceneView.js:17)
in SceneView (at DrawerScreen.js:21)
in DrawerScreen (at withCachedChildNavigation.js:69)
...

no one works for me,legacyImplementation cause ListHeaderComponentใ€ListFooterComponentnot work;disableVirtualizationis deprecated.

As my current project rely a lot on FlatLists, I took the time to create this article gathering every technique I could find around the internet that should enhance a FlatList.

Any contribution would be really helpful!

@bamne123's solution worked for me. It is running great.

This is still happening, in android a FlatList with a few images consumes a lot of memory and is not beign released, iOS works ok

Hi Folks, Please have a look on demo for listview performance in React native with images(5mb each).

React Native Experiment

Used - RecyclerListView & FastImage

For me, adding removeClippedSubviews and choosing a relevant keyExtractor did the trick. (Eg keyExtractor = {(item) => item} for a list of unique strings).

In my case the problem was in using contentContainerStyle with paddings and this causes FlatList to go crazy. Replace paddings with header/footers solves a problem.

UPD: Header and footer doesn't solve a problem, but adding them as part of my data (first and last element) works.

using contentContainerStyle with paddings and this causes FlatList to go crazy

uhm that seems a faily "focused" issue, would you mind opening an issue dedicated to that?

Same problem here. 2 items in FlatList with images of 200kb and crash on release build.

My use case:

  • I am using "react": "16.4.1" and "react-native": "0.56.0"
  • I have a long list of tiled network images. Original size: 410 x 410 px. Tile size: 125 pt x 125 pt.
  • There are a total of 263 items on this particular set (87 rows).
  • I am using react-native-navigation which already improves perf but the list was lagging when scrolling fast.
  • My FlatList has a numColumns={3}. I use the keyExtractor function.

I was able to make it super smooth and fast on an Moto G6 Android phone by making the following changes:

Performance boosters

  • Use import FastImage from ["react-native-fast-image"; to replace Image. Package
  • Make my renderItem a React.PureComponent.
  • Use getItemLayout to specify the size of the item.
  • Set removeClippedSubviews={true}.
  • Set initialNumToRender={27} as my view fits about 15 items (3 x 5 grid)
  • Set windowSize={41}.

I turned Perf Monitor on. JS Dev Mode off. JS Minify on.

Before the changes, on the Moto G6...

After loading the app:

UI: Oscillated around 2 - 60 fps.
130 dropped so far.
6 stutters so far.
JS: Oscillated between 8 - 59 fps.

While scrolling fast from top to bottom to top twice. These were the results:

UI: Oscillated around 2-58 fps.
519 dropped so far.
26 stutters so far.
JS: Oscillated between 3 - 57 fps.

It got laggier as I got to the bottom of the list and even laggier as I scrolled back up.

After applying the performance boosters to the FlatList, on the Moto G6...

After loading the app:

UI: Oscillated around 47- 59 fps.
29 dropped so far.
3 stutters so far.
JS: Oscillated between 43 - 59 fps.

While scrolling fast from top to bottom to top twice. These were the results:

UI: Stable around 59 fps.
40 dropped so far.
3 stutters so far.
JS: Stable around 59 fps.

The performance vastly improved!

When using Image instead of FastImage there is a bit of fast fading in when scrolling fast. Images at the very bottom will have its placeholder image and then load. With FastImage the fading is gone, images load instantaneously and stay loaded in subsequent scrolls. I think FastImage overcomes the tradeoff of gradual loading brought up by removeClippedSubviews={true}.

Will the performance be better without images?

Removing the FastImage element, on the Moto G6...

After loading the app:

UI: Oscillated fast around 3- 59 fps.
55 dropped so far.
3 stutters so far.
JS: Oscillated between 4 - 59 fps.

While scrolling fast from top to bottom to top twice. These were the results:

UI: Stable around 59 fps.
68 dropped so far.
3 stutters so far.
JS: Stable around 59 fps.

There's not much difference. It was better when having FastImage.

I am very pleased on how performant the list became! I am sure that more can be done to improve it. But so far, without having to implement infinite scrolling techniques, the properties of FlatList alone where fantastic for this use case.

Edit: I apologize. While scrolling with the performance boosters, the JS fps oscillate between 35 - 59 fps on the first top to bottom scroll using FastImage. Subsequent scrolling oscillates between 49 - 59 fps.

Better than FastImage, use resizeMethod="resize" on your image to configure Fresco in android, it gives you a cpu overhead but ram goes much lower

@kelset, I see you as batman, superman, The Avengers of the React Native... Any solution? I'm diying with this. Please, save me.

Using RN 0.57.4
React 16.6.1

If I remove the Image, Flatlist works fine... otherwise, my app go away

I suggest that you try the solutions listed above, such as:

We are working hard on improving Android perfs from the ground up (a part of this should already land in 0.58) - but also a lot of work should be doable by changing your code. I recommend this article to better understand what in your app may be creating a ton of overhead.

@ithustle any workaround yet? I think we need to dig it deeper further simply using components as it is wont work. I have a bit complex UI i.e nested flatList. Its like each cell has its own horizontal flatList. it works great on iPhone X but breaking on low end devices due to high memory.

If it's a performance problem caused by listview
You can try this library
react-native-nlist

https://github.com/Flipkart/recyclerlistview solved the performance issue for me

I needed to render 300 checkbox-list-items. I naively tried to set initialNumToRender={20}and maxToRenderPerBatch={280}. There was a slight delay (~700ms ยฑ 100) in the beginning, but then surprisingly I got a complete list in one _maxToRenderPerBatch_ go and could interact with it smoothly.

P.S. Given that the (reusable) ListItem component is quite complex, as it considers several scenarios for rendering.

Make sure you test that on slower devices - not just an emulator - to get a better indication of real world performance.
On Jan 14, 2019, 3:33 PM -0700, Igor Smirnov notifications@github.com, wrote:

I needed to render 300 checkbox-list-items. I naively tried to set initialNumToRender={20} and maxToRenderPerBatch={280}. There was a slight delay (~700ms ยฑ 100) in the beginning, but then surprisingly I got a complete list in one maxToRenderPerBatch go.
โ€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

Also these configuration helped to achieve better performance. initialNumToRender={30} maxToRenderPerBatch={30} windowSize={101}. I don't know, at the end it felt that it is about the best combination of the properties, perhaps, it is a quick fix for someone.

Hi, I have the same problem on my react-native V0.54 app... a FlatList with images (more than 300)... the app work fine with IOS, but crash with Android... I saw that the RAM was exploding (from ~120MB to +300MB which lead to a crash). Even when I limit the number of cards, I go from ~120MB to ~220MB only with 30 images
Tests made on simulator Adroid with 1Go Ram on Android 5.1.1 - API 22

I Tried to change component, use libs more and more complex, but nothing is working... Seems that FlatList with Images (react-native image and fast-image gives the same results) lead to a hard memory explosion on Android

I went as far as I can, someone tried to resolve this ( and perhaps succeed ?)

Setting removeClippedSubviews={true} was working for me until the 0.58 release.
With 0.59 my FlatList is lagging again on Android :(

ops, sorry: I was checking the platform using Platform.android instead of Platform.OS === 'android' (change in rn 0.59).
Anyway, removeClippedSubviews is the default for android now... and in my case does the trick.

Would be nice a native Recycler FlatList, like ListView.builder() in Flutter.

Any best solution for this in flatlist?

I am also facing the issue while scrolling the scrolling performance is not good in iOS. Smoothness is not there.

@JanithaR Any solution which is in Flatlist itself?

There are so many things you could do. For a start, could you let me know what you have already tried?

@JanithaR My Flatlist is like below. I have added legacyImplementation, shouldComponentUpdate an soon. Kindly refer below

Also, I can able to see a white space while scrolling a large list

```
ref={(ref) => { this.flatListRef = ref; }}
data={Items}
renderItem={({ item }) => this.renderList(item)}
numColumns={2}
extraData={this.props.pagination}
keyExtractor={item => item.id}
onEndReached={this._handleMoreItems}
maxToRenderPerBatch={10}
initialNumToRender = {14}
shouldComponentUpdate= {this.shouldItemUpdate()}
onEndReachedThreshold={0.001}
ListFooterComponent={this._renderFooter}
legacyImplementation = {true}
bounces = {false}
onMomentumScrollEnd={e => this.scroll(e.nativeEvent.contentOffset)}
/>

```

I'm not really sure why you have this,
shouldComponentUpdate= {this.shouldItemUpdate()}

This hasn't solved any problems for me in the past.
legacyImplementation = {true}

Instead of,
renderItem={({ item }) => this.renderList(item)}
write,
renderItem={this.renderList}

Do what's said here. https://facebook.github.io/react-native/docs/optimizing-flatlist-configuration#list-items Try to make your list item components as light and restricted as possible.

I need to pass the item for sure.

renderList(item){
return (
  <TouchableOpacity activeOpacity = { .5 } >
        <View style={{backgroundColor: 'white', alignItems: 'center'}}>
          <FastImage style={{width: Width, height: Height, margin:6}}
            resizeMode={FastImage.resizeMode.contain}
            source={item.uri}/>
            {this.renderName(item.name)}
            {this.renderClass(item.class)}
        </View>
      </TouchableOpacity>
)}

I am also stuck with this.

+1

+1

@nihp , @xhirazi ,@iagorm,

Have you tried Hermes or react-native-v8?
I was also facing similar issued, but in my case, react-native-v8 solved it for me.

I have also published the article regarding the same.

https://medium.com/walmartlabs/react-native-memory-profiling-jsc-vs-v8-vs-hermes-1626949a653b

My app memory drop from 1.3GB to 288MB after changing to react-native-v8. It can even handle 1000 + uncompress big pic in the flat list, general response become much faster, upgrade process was amazingly smooth. This is a true life savior. It should be the default engine for android. Thx bhaskarGyan!

@naqvitalha : After breaking my head with the jank caused by FlatList, I finally moved to recyclerlistview and am really loving it.
For folks who are wondering about the scroll performance difference, here's a before and after video.

  1. FlatList sucks : https://drive.google.com/open?id=1JF8i7jVWSM3l7MU12hxWFd6glhKWpJsR

  2. RecyclerListView is great: https://drive.google.com/open?id=1JAZRYeetDbf5tvxZCnvtM6jY5WfMDEHR

There's a weird jank when scrolling with FlatList which starts happening beyond 70 items.

@naqvitalha : Please support reverse mode for chat use cases. ScaleY: -1 approach is non-intuitive, heavy on render (because of the extra transforms causing entire list to be re-rendered if a new message is added) and also doesn't float messages on top if there's only 1 or 2 messages.

Screenshot_20200313-032510

As requested, here is the source code for the RecyclerListView:

import {BaseScrollView, DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';

export class RecyclerViewNative extends React.PureComponent {
    constructor(props) {
        super(props);
        this.ref = React.createRef();

        const { data, inverted } = this.props;
        const array = inverted ? data.slice().reverse() : data;
        const dataProvider = new DataProvider((r1, r2) => {
            return r1 !== r2;
        }).cloneWithRows(array);

        this.state = {
            dataProvider,
        };

        this.layoutProvider = new LayoutProvider((i) => {
            return this.state.dataProvider.getDataForIndex(i).type;
        }, (type, dim) => {
            dim.width = WINDOW_INNER_WIDTH;
            dim.height = 100;           // TODO: Try to get this more accurate
        });
    }
    componentDidUpdate(prevProps, prevState, snapshot) {
        const oldData = prevProps.data;
        const newData = this.props.data;

        // TODO: Handle message deletes as well
        if (newData.length > oldData.length) {
            const array = this.props.inverted ? newData.slice().reverse() : newData;
            this.setState(prevState => ({
                dataProvider: prevState.dataProvider.cloneWithRows(array, 0)
            }));
        }
    }

    renderRow = (type, data) => {
        const { renderItem, inverted } = this.props;
        const elem = renderItem(data, data.idx);
        const transform = inverted ? [{ scaleY: -1 }] : [];
        return <View style={{ width: '100%', transform }}>{elem}</View>;
    };

    render() {
        const { inverted } = this.props;
        const { dataProvider } = this.state;
        const transform = inverted ? [{ scaleY: -1 }] : [];
        return (
            <View style={{ height: '100%', width: '100%', transform, paddingTop: 5 }}>
                <RecyclerListView rowRenderer={this.renderRow} ref={this.ref}
                                  forceNonDeterministicRendering={true}
                                  dataProvider={dataProvider}
                                  layoutProvider={this.layoutProvider}/>
            </View>
        );
    }
}

Older FlatList I was using:

import {FlatList, View} from 'react-native';
import cnsole from 'loglevel';


export default class ScrollableList extends React.PureComponent {
    constructor(props) {
        super(props);
        this.ref = React.createRef();
    }

    refElem = () => this.ref.current;

    keyExtractor = ({ item, index }) => index;
    renderItem = ({ item, index }) => {
        const { itemRenderFn } = this.props;
        return itemRenderFn(item, index);
    };
    onEndReached = () => {
        cnsole.info('onEndReached');
    };

    render() {
        const { style, flatListProps, inverted, data } = this.props;
        const dataProp = inverted ? data.slice().reverse() : data;
        const contentContainerStyle = inverted ? { flexGrow: 1, justifyContent: 'flex-end' } : {};
        return (
            <View style={{ ...style, display: 'flex', flexDirection: 'column' }} ref={this.ref}>
                <FlatList
                    inverted={inverted} contentContainerStyle={contentContainerStyle}
                    nestedScrollEnabled={true}
                    data={dataProp}
                    renderItem={this.renderItem}
                    keyExtractor={this.keyExtractor}
                    extraData={{}}
                    onEndReached={this.onEndReached}
                    {...flatListProps}
                />
            </View>
        );
    }
}

@gagangoku Looks great but not perfect. Unfortunately, as long as there's a bridge in RN we will have to be satisfied with this.

The solution for this would be wrapping the native RecyclerView, Flatlist is just an abstraction of reusable cells, but it uses ScrollView under the hood.

@Edit: I did wrap the RecyclerView and the performance is ridiculously higher than Flatlist.

I dont know what to do with flatlist, more than 1000 way I used but still is not fast while scrolling even when put numColumns in horizontal mode app crash and closed.

@iagormoraes How have you used it bro

@iagormoraes How have you used it bro

I've created a native component, with view manager class and created a class to wrap a RecyclerView. the list items I created in XML layout from android as was too complex to pass each element of the list item from RN to native.

@iagormoraes thank you, but I dont know, how can I create native android ios module for react-native

@iagormoraes thank you, but I don't know, how can I create native android ios module for react-native

There is a tutorial on docs from RN but you can find other articles regarding it: https://reactnative.dev/docs/native-components-android

I spent the last several days investigating this issue for myself. Wanted to quickly document the solution/workaround I found. I won't go into too much detail on how I got to to the fix that works for me, unless anyone finds this useful and wants info. Just note that I tried a whole lot of other stuff, including every solution I see in this thread.

Solution: something to the effect of this layout below. Render a piece of text at the top of the list. You might be able to use a list header, I didn't test quite that much since this has been a multi-day bug hunt. The most basic version of this which still works for me looks roughly like this:

render() {
  return (
    <View style={{ display: 'flex', flex: 1, }}>
      <Text style={{ fontSize: 0.1, }}>&nbsp;</Text>
      <View style={{ flex: 1 }}>{this.renderYourList()}</View>
    </View>
  );
}

This made a 10+ second scroll lag fully disappear - its totally normally performant for me now. It doesn't matter what the text is, I'm using a 0.1 font size &nbsp; that is colored the same as background right now in my app. But the text does have to be there - removing it or replacing the element with something else doesn't work (or at least, nothing I've found so far works). This does result in what appears to be a small margin/border on the top of the list, which works fine for me so I've not done anything more to it - I don't know if any further tweaks could effectively hide it but retain the fix.

I don't have a full understanding of why this works, I just know it worked for me. I assume it has something to do with blending, but I'm a bit too worn out to dig deeper right now. Hopefully this helps others, or helps FB address the underlying issue.

we are in 2020 and you can use the react-native flatlist prop windowSize={Number} .
you can set your windowSize as large as you want depending on your performances tradeoffs .

for example for my case, I set windowSize to 201 which is equivalent to 201 view ports 100 below 100 above and the current one .
With this the scroll was smooth enough . try this see

Try big lists Mr. Break, Flatlist is horrible for huge lists.

Regards,
Gagan,
CEO @HeloProtocol,
+91-9008781096,
LinkedIn https://www.linkedin.com/in/gagan-deep-singh87/

On Thu, 11 Jun 2020 at 00:54, Mr Break; notifications@github.com wrote:

we are in 2020 and you can use the react-native flatlist prop
windowSize={Number} .
you can set your window size case large as you want depending on your
performances tradeoffs

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/13413#issuecomment-642209248,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAEFA4OGHNLYFA4YL7BCJXTRV7MX5ANCNFSM4DHBTFLQ
.

Most of people only because of flatlist is witching to flutter. I dont know why react-native team is not considering this big issue.

Should change all my solution to flutter just for this issue?
My app needs to render large lists. And even RecyclerListView goes slow, a little bit better. But still slow.

Should change all my solution to flutter just for this issue?
My app needs to render large lists. And even RecyclerListView goes slow, a little bit better. But still slow.

If you are talking about the package of react native "RecyclerListView" it is slow because it does some bridging between JS side with java side not in background and in a progressive way from what I saw by using it, it render a blank list until the list is done (talking about thousands of items). I totally agree that React Native should have wrapped the native RecyclerView from Android and UICollectionView from iOS, I've done it on the app but I couldn't make it in a generic way as you have to pass a viewholder, but it destroys in performance regarding to virtualized list.

I solved this issue by switching to react native V8 js engine. I think the root problem is some issue related the native js engine in android, having some memory leak. react native team cannot fix those error. For iOS, it works fine. You may try Hermes, too.

I had a mix of video contents, Webviews, and images as flatlist items. I found lag when I reached video or Webview content during the scroll. Switched to V8 and scrolling is now smooth. Not facing any lag.

@Sine99 , Could you please let me know, how you have switched to v8?

@Sine99 , Could you please let me know, how you have switched to v8?

@muhammadwafa https://github.com/Kudo/react-native-v8 u can follow their instructions. U just need to make the changes in the two build.gradle files.

@Sine99 thank you very much, Could you please let me know, Why and When should we use V8 engine instead of Javascript Core, what is the benefit of it?

@Sine99 thank you very much, Could you please let me know, Why and When should we use V8 engine instead of Javascript Core, what is the benefit of it?

It's just better in terms of a Javascript engine that should run on limited hardware capabilities.
https://github.com/Kudo/react-native-js-benchmark

@JanithaR thank you very much,

Are you meaning react-native + v8engine only works on few devices ?

@JanithaR thank you very much,

Are you meaning react-native + v8engine only works on few devices ?

No. I'm just saying it performs better. https://v8.dev/

@Sine99 thank you very much, Could you please let me know, Why and When should we use V8 engine instead of Javascript Core, what is the benefit of it?

@muhammadwafa you can check below for a comparison of V8 with JSC and Hermes

https://medium.com/walmartglobaltech/react-native-memory-profiling-jsc-vs-v8-vs-hermes-1626949a653b

@bhaskarGyan thank you very much I already read it your topic on medium thanks for that.
But there everything was about memory usage, nothing about speed and performance.

My concerns is why react-native team theirselves are not deciding to use v8 engine by default, may there is cons of it, and I want to know that, the pros and cons of using v8, because I have more than 10k users and some users are complaining about the chat list specially while they are scrolling fast.

My concerns is why react-native team theirselves are not deciding to use v8 engine by default, may there is cons of it, and I want to know that, the pros and cons of using v8, because I have more than 10k users and some users are complaining about the chat list specially while they are scrolling fast.

JSC was used for a long time (heavy, bulky, outdated etc.) and then made V8 (compiles to machine code) also available but, optional. Why optional? I really don't know. Facebook still wasn't happy so they built Hermes specifically to be used by React Native on Android devices.

I believe starting from 0.63 it is the default engine. Don't trouble yourself with V8 too much.

Thank you very much, and one the last question, if you have time kindly let me know it.

If I used v8 engine, then Do I need Hermes?

If I used v8 engine, then Do I need Hermes?

I linked to a benchmark repo above. Look at the results spreadsheet and decide for yourself. Personally, Hermes is good enough for me.

windowSize

GG, it worked for me, but we have to pay attention to the use of memory, because this feature requires a lot. My flatList is very quick, but I will do more tests so that I can conclude this question for my project.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anchetaWern picture anchetaWern  ยท  3Comments

DreySkee picture DreySkee  ยท  3Comments

axelg12 picture axelg12  ยท  3Comments

vikeri picture vikeri  ยท  3Comments

grabbou picture grabbou  ยท  3Comments