clauderic / react-tiny-virtual-list

A tiny but mighty 3kb list virtualization library, with zero dependencies 💪 Supports variable heights/widths, sticky items, scrolling to index, and more!
https://clauderic.github.io/react-tiny-virtual-list/
MIT License
2.46k stars 165 forks source link

Perf #45

Open bjoerge opened 6 years ago

bjoerge commented 6 years ago

Hi @clauderic, thanks for this library!

I'm having a few performance issues which seem to be caused by onScroll triggering a setState which triggers a re-render. Here's a capture of scrolling through a list with a renderItem that only render simple <span>Hi</span>-items:

image

For reference, this is using the dev build of React 15.6.1, with 6x CPU slowdown.

This can be improved by adding the scroll listener as a passive event listener instead of using onScroll (AFAIK React does not support specifying events as passive using on*-props, so it must be set up in componentDidMount).

Additionally, to increase performance even more the VirtualList component could support a debounce-prop, which takes a number of milliseconds to debounce the handleScroll method with.

Would you be interested in a PR for this?

nicubarbaros commented 6 years ago

That would be amazing @bjoerge, currently I am debouncing but still, I am seeing performance drops.

bjoerge commented 6 years ago

PR submitted: #47

yogurt1 commented 6 years ago

What if use requestAnimationFrame?

componentDidMount() {
  let scrollTop = 0;
  const step = () => {
    if (scrollTop !== this.rootNode.scrollTop) {
      scrollTop = this.rootNode.scrollTop;
      this.handleScroll(scrollTop);
    }
    requestAnimationFrame(step);
  };
  this.rafId = requestAnimationFrame(step);
}

componentWillUnmount() { cancelAnimationFrame(this.rafId); }

react-sentinel as example

damianobarbati commented 6 years ago

Any tips to have a 60fps framerate when scrolling?

ymaz commented 6 years ago

what about to start using transform: translate3d instead of top?

clauderic commented 6 years ago

what about to start using transform: translate3d instead of top?

In my experience testing this, using transform was actually slower.

ymaz commented 6 years ago

@clauderic thanks! I'm just curious, in your perf test, did you use translate3d exact 3d option for transform or 2d (translatey)? From my understanding, translate3d should create one more virtual layer of context, which might help in terms of performance. something like that

transform: translate3d(0px, %yourTopValue%px, 0px);

and change only %yourTopValue%?

damianobarbati commented 6 years ago

For anyone who may stumble on it: this will cause any position:fixed element inside to behave like a position:absolute relative to the transformed element. Why worrying about it? Because in a current project of mine I have columns with truncated overflowing content (with ellipsis). To show full content I use a fixed positioned tooltip on the column with the full content once hovering over the column. I had to find out that the virtual table was using the transform and that's why it was not possible.