Skip to content

Instantly share code, notes, and snippets.

@clauderic
Last active February 13, 2019 18:02
Show Gist options
  • Save clauderic/ed1ec490f946316cb7404b373943eb9e to your computer and use it in GitHub Desktop.
Save clauderic/ed1ec490f946316cb7404b373943eb9e to your computer and use it in GitHub Desktop.
Conditional rendering in React Virtualized based on Scroll Speed
import React, {PureComponent} from 'react';
import {List} from 'react-virtualized';
import debounce from 'lodash/debounce';
class ScrollSpeed {
clear = () => {
this.lastPosition = null;
this.delta = 0;
};
getScrollSpeed(scrollOffset) {
if (this.lastPosition != null) {
this.delta = scrollOffset - this.lastPosition;
}
this.lastPosition = scrollOffset;
window.clearTimeout(this._timeout);
this._timeout = window.setTimeout(this.clear, 50);
return this.delta;
}
}
const SPEED_THRESHOLD = 50; // Tweak this to whatever feels right for your app
const SCROLL_DEBOUNCE_DURATION = 150; // In milliseconds
class App extends PureComponent {
getScrollSpeed = new ScrollSpeed().getScrollSpeed;
handleScroll = ({scrollTop}) => {
// scrollSpeed represents the number of pixels scrolled since the last scroll event was fired
const scrollSpeed = Math.abs(this.getScrollSpeed(scrollTop));
if (scrollSpeed >= SPEED_THRESHOLD) {
this.setState({
isScrollingFast: true,
});
}
// Since this method is debounced, it will only fire once scrolling has stopped for the duration of SCROLL_DEBOUNCE_DURATION
this.handleScrollEnd();
}
handleScrollEnd = debounce(() => {
const {isScrollingFast} = this.state;
if (isScrollingFast) {
this.setState({
isScrollingFast: false,
});
}
}, SCROLL_DEBOUNCE_DURATION);
rowRenderer = () => {
const {isScrollingFast} = this.state;
// Conditionally render your rows based on isScrollingFast...
}
render() {
return (
<List
width={300}
height={300}
rowCount={500}
rowHeight={20}
rowRenderer={this.rowRenderer}
onScroll={this.handleScroll}
/>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment