question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SectionList (and probably VirtualizedList/FlatList) fails to batch row renders on re-renders

See original GitHub issue

Is this a bug report?

Yes

Have you read the Contributing Guidelines?

Yes

Environment

  1. react-native -v: react-native-cli: 2.0.1 react-native: 0.48.3
  2. node -v: v8.5.0
  3. npm -v: 5.3.0
  4. yarn --version: 1.0.2

Then, specify:

  • Target Platform: iOS, Android
  • Development Operating System: macOS 10.12.6
  • Build tools: n/a

Steps to Reproduce

  1. Create a SectionList (I expect it’s the same for FlatList and VirtualizedList too) with a large number of items – several hundred.
  2. After it has rendered, trigger a re-render of the SectionList by changing its data. I do this by applying a filter to the data.

Expected Behavior

The initial render of the SectionList works well for me. My understanding is: when SectionList is first rendered, it renders a minimal number of items (according to initialNumToRender) and then releases the JS thread to allow user interaction with the page. It then continues to render off-screen rows in batches. Every second or so it will render a batch (of size determined by maxToRenderPerBatch) and then release the JS thread again. It continues this loop until it has filled the window large enough to satisfy the windowSize prop. In my application, this works out to a window of around 70 rows with the default value of windowSize=21. This is a Good Thing because it means that when a user starts scrolling down, the window provides a buffer of offscreen rows that are ready to be displayed.

So that’s all good. The issue I’m having is when a user filters the list. My app provides a button which applies a filter to the list by some condition. When the SectionList re-renders after this button is pressed, I would expect the SectionList to only render initialNumToRender rows, and then release the JS thread, and then incrementally re-populate the window using the same procedure as in the initial render.

Actual Behavior

However, what actually happens is that SectionList re-renders every row in the window at once, locking up the JS thread until they have all re-rendered. In practical terms, this makes my application appear to lag a lot, as it takes several seconds to render all 70 rows. So my question is: why does SectionList re-render the whole window before releasing the JS thread? Is this a bug? Is there a way I can get it to only render initialNumToRender rows on a re-render, and then re-populate the window gradually for a smoother user experience?

Reproducible Demo

I tried to create a demo but couldn’t get snack to work very well.

UPDATE: I got a demo working : https://snack.expo.io/H1osQ8fiW

I’ve used a FlatList since it’s simpler than a SectionList, but the same problem is there. I’ve set updateCellsBatchingPeriod to 4 seconds to make it clear when the batched updates are happening.

  1. When the app loads, open the console. When a row is rendered, a log message appears. Every 4 seconds, 10ish messages should appear, corresponding to a batch of offscreen rows being rendered.
  2. Don’t scroll up or down – you don’t need to. Wait until new messages stop appearing – this will take about 30 seconds due to the large updateCellsBatchingPeriod I’ve set. It will end up rendering about 70 rows.
  3. Now press the “Toggle data” button at the bottom of the page. This will toggle the data set being displayed. You will see a noticeable stutter in the UI, and then the [A1, A2, A3…] values will be replaced with [B1, B2, B3…] values.
  4. Look at the console when you press the button. Even though there is only space on the screen for <10 rows, you’ll see that all 70 rows are immediately re-rendered, with none of the batching that the first render displayed.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:4
  • Comments:14

github_iconTop GitHub Comments

5reactions
haojiezhangcommented, Jun 1, 2018

I can confirm this is a bug. This is happening to me too!

3reactions
bdrobinsoncommented, Feb 23, 2018

This is still an issue for us.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React-Native FlatList performance problems with large list
Blank areas means that the VirtualizedList couldn't render your items fast enough, so you enter on a part of your list with non...
Read more >
Optimizing Flatlist Configuration - React Native
It is a VirtualizedList prop that can be passed through FlatList . This controls the amount of items rendered per batch, which is...
Read more >
How to optimize your react native flatlist | by Amirali Esmaeili
Recently at Sanjagh we faced an awful rendering performance in first page of sign up process which is a simple section list with...
Read more >
Better List Views in React Native
This is done by 'virtualizing' elements that are outside of the render window by completely unmounting them from the component hierarchy and ...
Read more >
Optimizing a React Native FlatList With Many Child Components
So 10 of them would mean ~300 components, probably more actually. ... passing static props around - as little re-renders as possible.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found