Skip to content

FlatList renders items way too often, resulting in poor performance #29946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dirkpostma opened this issue Sep 14, 2020 · 9 comments
Closed

FlatList renders items way too often, resulting in poor performance #29946

dirkpostma opened this issue Sep 14, 2020 · 9 comments
Labels
Component: FlatList Needs: Issue Manager Attention Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@dirkpostma
Copy link
Contributor

dirkpostma commented Sep 14, 2020

Description

<FlatList> should enhance the performance of rendering lists with lots of items. Unfortunately, there (still) exists a bug that leads to way too many re-renders of list items, resulting in poor performance.

Code snippet:

const App = () => {
  const data = generateData(20);

  return (
    <FlatList
      data={data}
      renderItem={({index}) => {
        console.log('renderItem', index);
        return <View style={styles.listItem} />;
      }}
    />
  );
};
[Mon Sep 14 2020 23:10:28.303]  LOG      Running "TryFlatList" with {"rootTag":801,"initialProps":{}}
[Mon Sep 14 2020 23:10:28.305]  LOG      renderItem 0
[Mon Sep 14 2020 23:10:28.305]  LOG      renderItem 1
[Mon Sep 14 2020 23:10:28.306]  LOG      renderItem 2
[Mon Sep 14 2020 23:10:28.306]  LOG      renderItem 3
[Mon Sep 14 2020 23:10:28.307]  LOG      renderItem 4
[Mon Sep 14 2020 23:10:28.308]  LOG      renderItem 5
[Mon Sep 14 2020 23:10:28.309]  LOG      renderItem 6
[Mon Sep 14 2020 23:10:28.309]  LOG      renderItem 7
[Mon Sep 14 2020 23:10:28.310]  LOG      renderItem 8
[Mon Sep 14 2020 23:10:28.311]  LOG      renderItem 9
[Mon Sep 14 2020 23:10:28.312]  LOG      renderItem 0.   <=  unnecessary render of item #0
[Mon Sep 14 2020 23:10:28.313]  LOG      renderItem 1.        following 9 also
[Mon Sep 14 2020 23:10:28.313]  LOG      renderItem 2
[Mon Sep 14 2020 23:10:28.314]  LOG      renderItem 3
[Mon Sep 14 2020 23:10:28.315]  LOG      renderItem 4
[Mon Sep 14 2020 23:10:28.316]  LOG      renderItem 5
[Mon Sep 14 2020 23:10:28.317]  LOG      renderItem 6
[Mon Sep 14 2020 23:10:28.317]  LOG      renderItem 7
[Mon Sep 14 2020 23:10:28.318]  LOG      renderItem 8
[Mon Sep 14 2020 23:10:28.319]  LOG      renderItem 9
[Mon Sep 14 2020 23:10:28.319]  LOG      renderItem 10
[Mon Sep 14 2020 23:10:28.320]  LOG      renderItem 11
[Mon Sep 14 2020 23:10:28.320]  LOG      renderItem 12
[Mon Sep 14 2020 23:10:28.321]  LOG      renderItem 13
[Mon Sep 14 2020 23:10:28.322]  LOG      renderItem 14
[Mon Sep 14 2020 23:10:28.323]  LOG      renderItem 15
[Mon Sep 14 2020 23:10:28.324]  LOG      renderItem 16
[Mon Sep 14 2020 23:10:28.324]  LOG      renderItem 17
[Mon Sep 14 2020 23:10:28.325]  LOG      renderItem 18
[Mon Sep 14 2020 23:10:28.326]  LOG      renderItem 19
[Mon Sep 14 2020 23:10:40.329]  LOG      renderItem 0  <=  again render of item #0
[Mon Sep 14 2020 23:10:40.331]  LOG      renderItem 1
[Mon Sep 14 2020 23:10:40.333]  LOG      renderItem 2
[Mon Sep 14 2020 23:10:40.334]  LOG      renderItem 3
[Mon Sep 14 2020 23:10:40.335]  LOG      renderItem 4
[Mon Sep 14 2020 23:10:40.336]  LOG      renderItem 5
[Mon Sep 14 2020 23:10:40.337]  LOG      renderItem 6
[Mon Sep 14 2020 23:10:40.338]  LOG      renderItem 7
[Mon Sep 14 2020 23:10:40.338]  LOG      renderItem 8
[Mon Sep 14 2020 23:10:40.339]  LOG      renderItem 9
[Mon Sep 14 2020 23:10:40.340]  LOG      renderItem 10
[Mon Sep 14 2020 23:10:40.341]  LOG      renderItem 11
[Mon Sep 14 2020 23:10:40.341]  LOG      renderItem 12
[Mon Sep 14 2020 23:10:40.342]  LOG      renderItem 13
[Mon Sep 14 2020 23:10:40.343]  LOG      renderItem 14
[Mon Sep 14 2020 23:10:40.343]  LOG      renderItem 15
[Mon Sep 14 2020 23:10:40.344]  LOG      renderItem 16
[Mon Sep 14 2020 23:10:40.345]  LOG      renderItem 17
[Mon Sep 14 2020 23:10:40.346]  LOG      renderItem 18
[Mon Sep 14 2020 23:10:40.346]  LOG      renderItem 19

This is on first mount, without having done any scrolling.

Related to:

Workaround

There is a workaround to solve performance issue: wrap the ListItems in React.memo (or use PureComponent or implement componentShouldUpdate). However, this is just a workaround and not the way it should work.

React Native version:

yarn react-native info
yarn run v1.22.4
$ /Users/dirkpostma/development/playground/TryFlatList/node_modules/.bin/react-native info
info Fetching system and libraries information...
System:
    OS: macOS 10.15.6
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 1.24 GB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 10.14.2 - /var/folders/p8/lc8f03hj4glfwjx1c0_39d8w0000gn/T/yarn--1600099516621-0.65803085701635/node
    Yarn: 1.22.4 - /var/folders/p8/lc8f03hj4glfwjx1c0_39d8w0000gn/T/yarn--1600099516621-0.65803085701635/yarn
    npm: 6.4.1 - ~/.nvm/versions/node/v10.14.2/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.9.3 - /Users/dirkpostma/.gem/ruby/2.4.9/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.7, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 19, 23, 27, 28, 29
      Build Tools: 27.0.3, 28.0.3, 29.0.2, 29.0.3, 30.0.0
      System Images: android-19 | Google APIs Intel x86 Atom, android-21 | Intel x86 Atom, android-21 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6308749
    Xcode: 11.7/11E801a - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_242 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1
    react-native: 0.63.2 => 0.63.2
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found
✨  Done in 3.53s.

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. git clone https://github.com/dirkpostma/react-native-flatlist-demo
  2. yarn
  3. cd ios; pod install; cd ..
  4. yarn ios
  5. inspect logs

Expected Results

On first mount, I would expect that all items would only be rendered at most once.

Snack, code example, screenshot, or link to a repository:

https://github.com/dirkpostma/react-native-flatlist-demo

@safaiyeh
Copy link
Contributor

I built this locally and seem to get different behavior. I'm not sure rendering every single cell is correct either. FlatList documentation also does not seem 100% clear on what it is supposed to do or what it is trying to achieve, clarification around that is necessary as well to manage expectations

Screen Shot 2020-09-15 at 9 18 10 PM

There is a workaround to solve performance issue: wrap the ListItems in React.memo (or use PureComponent or implement componentShouldUpdate). However, this is just a workaround and not the way it should work.

Unfortunately lists are hard, I doubt there can be an implementation that works for all use cases without your own optimizations. React Native even logs VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc.

@dirkpostma
Copy link
Contributor Author

dirkpostma commented Sep 16, 2020

@safaiyeh I'm so sorry.. I forgot to push my latest commit that I produced the results of my report with. My failure. I just pushed it, commit 3811b0617011e253f48b355640277ed4453b3b0e, "Simplify example for bugreport". The commit you had was with the workaround using React.memo.

I agree lists are hard. And yes, I agree that clarification of docs would be good too.

Nevertheless, I see lot of inefficient behaviour, in certain cases thousands of unnecessary re-renders (or shallow equal comparisons if you apply shouldComponentUpdate / React.memo / PureComponent). These are still a waste. If I'm scrolling down (swipe up), I never expect re-renders of the first X items. I cannot think of a usecase that that would be necessary. If I run for first time, I never expect duplicate renders.

If you checkout commit dbd926d1363e4e050660fc214d799d770b26aff0, this is what just happend (on my machine), on first run, without having done any interaction:

[Wed Sep 16 2020 08:16:08.349]  LOG      Running "TryFlatList" with {"rootTag":11,"initialProps":{}}
[Wed Sep 16 2020 08:16:08.351]  LOG      rendering 0
[Wed Sep 16 2020 08:16:08.351]  LOG      rendering 1
[Wed Sep 16 2020 08:16:08.351]  LOG      rendering 2
[Wed Sep 16 2020 08:16:08.351]  LOG      rendering 3
[Wed Sep 16 2020 08:16:08.352]  LOG      rendering 4
[Wed Sep 16 2020 08:16:08.352]  LOG      rendering 5
[Wed Sep 16 2020 08:16:08.352]  LOG      rendering 6
[Wed Sep 16 2020 08:16:08.352]  LOG      rendering 7
[Wed Sep 16 2020 08:16:08.353]  LOG      rendering 8
[Wed Sep 16 2020 08:16:08.353]  LOG      rendering 9
[Wed Sep 16 2020 08:16:08.457]  LOG      rendering 0
[Wed Sep 16 2020 08:16:08.471]  LOG      rendering 1
[Wed Sep 16 2020 08:16:08.487]  LOG      rendering 2
[Wed Sep 16 2020 08:16:08.489]  LOG      rendering 3
[Wed Sep 16 2020 08:16:08.491]  LOG      rendering 4
[Wed Sep 16 2020 08:16:08.505]  LOG      rendering 5
[Wed Sep 16 2020 08:16:08.507]  LOG      rendering 6
[Wed Sep 16 2020 08:16:08.508]  LOG      rendering 7
[Wed Sep 16 2020 08:16:08.521]  LOG      rendering 8
[Wed Sep 16 2020 08:16:08.523]  LOG      rendering 9
[Wed Sep 16 2020 08:16:08.525]  LOG      rendering 10
[Wed Sep 16 2020 08:16:08.553]  LOG      rendering 11
[Wed Sep 16 2020 08:16:08.555]  LOG      rendering 12
[Wed Sep 16 2020 08:16:08.589]  LOG      rendering 13
[Wed Sep 16 2020 08:16:08.606]  LOG      rendering 14
[Wed Sep 16 2020 08:16:08.623]  LOG      rendering 15
[Wed Sep 16 2020 08:16:08.640]  LOG      rendering 16
[Wed Sep 16 2020 08:16:08.656]  LOG      rendering 17
[Wed Sep 16 2020 08:16:08.673]  LOG      rendering 18
[Wed Sep 16 2020 08:16:08.677]  LOG      rendering 19
[Wed Sep 16 2020 08:16:08.701]  LOG      rendering 0
[Wed Sep 16 2020 08:16:08.702]  LOG      rendering 1
[Wed Sep 16 2020 08:16:08.702]  LOG      rendering 2
[Wed Sep 16 2020 08:16:08.703]  LOG      rendering 3
[Wed Sep 16 2020 08:16:08.705]  LOG      rendering 4
[Wed Sep 16 2020 08:16:08.706]  LOG      rendering 5
[Wed Sep 16 2020 08:16:08.707]  LOG      rendering 6
[Wed Sep 16 2020 08:16:08.708]  LOG      rendering 7
[Wed Sep 16 2020 08:16:08.708]  LOG      rendering 8
[Wed Sep 16 2020 08:16:08.709]  LOG      rendering 9
[Wed Sep 16 2020 08:16:08.709]  LOG      rendering 10
[Wed Sep 16 2020 08:16:08.710]  LOG      rendering 11
[Wed Sep 16 2020 08:16:08.710]  LOG      rendering 12
[Wed Sep 16 2020 08:16:08.711]  LOG      rendering 13
[Wed Sep 16 2020 08:16:08.712]  LOG      rendering 14
[Wed Sep 16 2020 08:16:08.712]  LOG      rendering 15
[Wed Sep 16 2020 08:16:08.713]  LOG      rendering 16
[Wed Sep 16 2020 08:16:08.713]  LOG      rendering 17
[Wed Sep 16 2020 08:16:08.715]  LOG      rendering 18
[Wed Sep 16 2020 08:16:08.715]  LOG      rendering 19
[Wed Sep 16 2020 08:16:08.716]  LOG      rendering 20
[Wed Sep 16 2020 08:16:08.716]  LOG      rendering 21
[Wed Sep 16 2020 08:16:08.717]  LOG      rendering 22
[Wed Sep 16 2020 08:16:08.718]  LOG      rendering 23
[Wed Sep 16 2020 08:16:08.718]  LOG      rendering 24
[Wed Sep 16 2020 08:16:08.719]  LOG      rendering 25
[Wed Sep 16 2020 08:16:08.719]  LOG      rendering 26
[Wed Sep 16 2020 08:16:08.720]  LOG      rendering 27
[Wed Sep 16 2020 08:16:08.720]  LOG      rendering 28
[Wed Sep 16 2020 08:16:08.720]  LOG      rendering 29
[Wed Sep 16 2020 08:16:08.789]  LOG      rendering 0
[Wed Sep 16 2020 08:16:08.790]  LOG      rendering 1
[Wed Sep 16 2020 08:16:08.790]  LOG      rendering 2
[Wed Sep 16 2020 08:16:08.791]  LOG      rendering 3
[Wed Sep 16 2020 08:16:08.791]  LOG      rendering 4
[Wed Sep 16 2020 08:16:08.791]  LOG      rendering 5
[Wed Sep 16 2020 08:16:08.792]  LOG      rendering 6
[Wed Sep 16 2020 08:16:08.792]  LOG      rendering 7
[Wed Sep 16 2020 08:16:08.792]  LOG      rendering 8
[Wed Sep 16 2020 08:16:08.793]  LOG      rendering 9
[Wed Sep 16 2020 08:16:08.793]  LOG      rendering 10
[... a few thousand lines more...]
[Wed Sep 16 2020 08:16:10.594]  LOG      rendering 183
[Wed Sep 16 2020 08:16:10.595]  LOG      rendering 184
[Wed Sep 16 2020 08:16:10.595]  LOG      rendering 185
[Wed Sep 16 2020 08:16:10.595]  LOG      rendering 186
[Wed Sep 16 2020 08:16:10.595]  LOG      rendering 187
[Wed Sep 16 2020 08:16:10.596]  LOG      rendering 188
[Wed Sep 16 2020 08:16:10.596]  LOG      rendering 189
[Wed Sep 16 2020 08:16:10.596]  LOG      rendering 190
[Wed Sep 16 2020 08:16:10.597]  LOG      rendering 191
[Wed Sep 16 2020 08:16:10.597]  LOG      rendering 192
[Wed Sep 16 2020 08:16:10.597]  LOG      rendering 193
[Wed Sep 16 2020 08:16:10.597]  LOG      rendering 194
[Wed Sep 16 2020 08:16:10.598]  LOG      rendering 195
[Wed Sep 16 2020 08:16:10.598]  LOG      rendering 196
[Wed Sep 16 2020 08:16:10.598]  LOG      rendering 197
[Wed Sep 16 2020 08:16:10.599]  LOG      rendering 198
[Wed Sep 16 2020 08:16:10.599]  LOG      rendering 199
[Wed Sep 16 2020 08:16:10.599]  LOG      rendering 200
[Wed Sep 16 2020 08:16:10.599]  LOG      rendering 201
[Wed Sep 16 2020 08:16:10.600]  LOG      rendering 202
[Wed Sep 16 2020 08:16:10.600]  LOG      rendering 203
[Wed Sep 16 2020 08:16:10.600]  LOG      rendering 204
[Wed Sep 16 2020 08:16:10.600]  LOG      rendering 205
[Wed Sep 16 2020 08:16:10.601]  LOG      rendering 206
[Wed Sep 16 2020 08:16:10.601]  LOG      rendering 207
[Wed Sep 16 2020 08:16:10.601]  LOG      rendering 208
[Wed Sep 16 2020 08:16:10.601]  LOG      rendering 209
[Wed Sep 16 2020 08:16:10.602]  LOG      rendering 210
[Wed Sep 16 2020 08:16:10.602]  LOG      rendering 211
[Wed Sep 16 2020 08:16:10.602]  LOG      rendering 212
[Wed Sep 16 2020 08:16:10.602]  LOG      rendering 213
[Wed Sep 16 2020 08:16:10.603]  LOG      rendering 214
[Wed Sep 16 2020 08:16:10.603]  LOG      rendering 215
[Wed Sep 16 2020 08:16:10.603]  LOG      rendering 216
[Wed Sep 16 2020 08:16:10.603]  LOG      rendering 217
[Wed Sep 16 2020 08:16:10.604]  LOG      rendering 218
[Wed Sep 16 2020 08:16:10.604]  LOG      rendering 219
[Wed Sep 16 2020 08:16:10.604]  LOG      rendering 220
[Wed Sep 16 2020 08:16:10.604]  LOG      rendering 221
[Wed Sep 16 2020 08:16:10.605]  LOG      rendering 222
[Wed Sep 16 2020 08:16:10.605]  LOG      rendering 223
[Wed Sep 16 2020 08:16:10.605]  LOG      rendering 224

=> 2756 renders on first run, see attached file for complete log. Ran on iPhone 11 simulator, DEV mode.

I think it would be good to dig into FlatList / VirtualizedList to solve these issues.
flatlist_log.txt
And update docs.

@Venon-IT
Copy link

I think you measure to peformance wrong way. Because you just printing index but there is https://reactnative.dev/docs/flatlist#initialnumtorender. I think you should measure performance with renderItem prop. Can you observe to how many times renderItem runs? I agree you, there is some bugs in Flatlist but maybe its not a bug

@dirkpostma
Copy link
Contributor Author

dirkpostma commented Sep 24, 2020

@Venon-IT

Can you observe to how many times renderItem runs?

Not sure why you ask this question, as I'm doing exactly that. Each time renderItem runs, a line is logged to the console. The amount of renders equals the amount of lines printed.

In simple example (https://github.com/dirkpostma/react-native-flatlist-demo/commit/3811b0617011e253f48b355640277ed4453b3b0e):

const App = () => {
  const data = generateData(20);

  return (
    <FlatList
      data={data}
      renderItem={({index}) => {
        console.log('renderItem', index);
        return <View style={styles.listItem} />;
      }}
    />
  );
};

In example with many (unnecessary) renders (https://github.com/dirkpostma/react-native-flatlist-demo/commit/a5c03ffc37b4b611da9801bd9e19173a58e19a6b):

function renderItem({item}: {item: Item}) {
  console.log(`rendering ${item.key}`);

  return (
    <View style={styles.listItem}>
      <Text>{item.name}</Text>
    </View>
  );
}

If I misunderstand you, can you clarify what you mean?

@akshgods
Copy link

akshgods commented Dec 8, 2020

same issue

@zhaoxing-msft
Copy link

same issue
and it seems that flatlist renders all items, even they are not in visualable area

@zhaoxing-msft
Copy link

https://stackoverflow.com/questions/45610547/reactnative-flatlist-render-all-items-at-once

I think the link above solves my problem.

I copied the key word in case of the link expires:
--------->
don't nest your FlatList in a ScrollList (or other kind of lists).
<---------

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jul 19, 2023
@github-actions
Copy link

This issue was closed because it has been stalled for 7 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: FlatList Needs: Issue Manager Attention Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests

6 participants