Skip to content

How to NOT re-render list rows when scrolling? #74

Closed

Description

@michael-land

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

Activity

  1. changed the title [-]How to reduce re-render when use overscan?[/-] [+]How to NOT re-render list rows when scrolling?[/+] on Oct 20, 2020
  2. mogelbrod commented on Oct 27, 2020

    @mogelbrod
    Contributor

    I think this could be a nice opt-in behavior to reduce the number of re-renders.

    Are your item components memoized though? Items that stay within the window shouldn't be re-rendered (IIRC) if they're memoized (via React.useMemo or React.PureComponent) and you make sure to key them on the virtualItems[x].index property, or something on the item data itself that is immutable.

  3. X7Becka commented on Apr 18, 2021

    @X7Becka

    Does maintainer watches the issues?

  4. tannerlinsley commented on Apr 18, 2021

    @tannerlinsley
    Member

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

  5. piecyk commented on Apr 18, 2021

    @piecyk
    Collaborator

    Overall as @mogelbrod suggested this need to be handled by memoizing the row result. For example, extracting row to it's own component and wrapping it with React.memo.

  6. piecyk commented on Apr 19, 2021

    @piecyk
    Collaborator

    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

  7. bestwebdeveloper commented on Aug 14, 2021

    @bestwebdeveloper

    @paulm17 Depending on how you serve images to a user. I guess there is a url in a src. If yes, then there is only browser caching may help. Another way is to convert images to a Blob on load and use this blob as a source for image instead of url then you will be able at least cache images after retrieving them, but this of cause will occupy more memory of the users.

  8. paulm17 commented on Aug 14, 2021

    @paulm17

    This is an old issue. I've actually dropped this lib and using react-window and also using indexDB as browser caching didn't help.

    So I consider my solution as a solution to my issue, no need to reply. Will be unsubbing from this thread too. 😄

  9. michael-land commented on Aug 14, 2021

    @michael-land
    Author

    I end up use my own version react-virtual, I think this PR #164 also implement it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions