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.

How to NOT re-render list rows when scrolling?

See original GitHub issue

Assume I have the following settings:

The container height: 400 The row height: 40

const virtual = useVirtual({
  size: 1000,
  parentRef,
  overscan: 20,
  estimateSize: useCallback(() => 40, [size]),
})

It seems that the container re-renders every visible row every time new row appears. This behavior maybe intentional but what if my row is heavyweight and the cost to re-render them is not trivial?

What I want to do is re-render only when the last row is visible.

In the above setup, I should see re-render happen once when i scroll to the 30th element, and insert next 20 element since overscan is 20.


Edit:

After play around with the source code, I see that setRange(prevRange => calculateRange(latestRef.current, prevRange)) actually cause the re-render every time index change.

I changed the if condition from

  if (!prevRange || prevRange.start !== start || prevRange.end !== end) {
    return {
      start: start,
      end: end
    };
  }

to


  if (!prevRange ||
    Math.abs(start - prevRange.start) > overscan - 1 ||
    Math.abs(end - prevRange.end) > overscan - 1
    ) {
    return {
      start: start,
      end: end
    };
  }

It reduce re-render from 999 to 50 when the data size is 1000 and overscan is 20.

Maybe we can allow developer to pass custom calculateRange function if they need to optimize performance? or improve calculateRange when overscan is used?

https://github.com/tannerlinsley/react-virtual/blob/master/src/index.js#L77

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
piecykcommented, Apr 19, 2021

Some quick points to consider when things start to be slow

  • as react-virtual is a hook, the whole component will re-render whit it. If it’s a complex one, best is to extract it to smaller one.
  • memoize the row result
  • when row update it’s internal state base on mouse actions, for example tooltip etc, one options is to disable the pointer-events when scrolling.

https://codesandbox.io/s/react-virtual-performance-list-pmyo2

2reactions
tannerlinsleycommented, Apr 18, 2021

Yep! Just prioritization. I’ll get to this issue soon.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Add option to not re-render list rows when scrolling #1028
Instead, I propose that there should be a way to tell List not to continually re-render visible rows when scrolling.
Read more >
How to stop re-rendering lists in React? - Alex Sidorenko
Components always re-render. First, let's simplify our example by removing all props from the Item . We will still update the parent state...
Read more >
javascript - react-window stop unnecessary rendering of child ...
I think this problem would solve if the parent list would stop propagating scroll event to child. I tried to add event.stopPropagation() and ......
Read more >
Rendering large lists in React: 5 methods with examples
Explore five methods for easily rendering large lists in React, including pagination, infinite scroll, and several libraries.
Read more >
FlatList - React Native
FlatList. A performant interface for rendering basic, flat lists, supporting the most handy features: Fully cross-platform.
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