Skip to content

Instantly share code, notes, and snippets.

@zz85
Last active July 26, 2022 18:59
Show Gist options
  • Save zz85/c1fc246d92b6bb747b948a7fa3e41321 to your computer and use it in GitHub Desktop.
Save zz85/c1fc246d92b6bb747b948a7fa3e41321 to your computer and use it in GitHub Desktop.
Prototype to make Scroll Position Sticky When Changing Dynamic Element Heights for React Infinite
function sum(total, next) {
return total + next;
}
var old = 0;
var NUM = 102;
var VariableInfiniteList = React.createClass({
componentDidMount: function() {
setInterval(this.changeElementHeights, 3000);
this.scrollDom = this.refs.container.refs.scrollable;
// console.log(this.refs.container.refs.scrollable, this.refs.container.refs.smoothScrollingWrapper);
},
getInitialState: function() {
return {
elementHeights: this.generateVariableElementHeights(NUM),
isInfiniteLoading: false
};
},
generateVariableElementHeights: function(number, minimum, maximum) {
minimum = minimum || 50;
maximum = maximum || 100;
var heights = [];
for (var i = 0; i < number; i++) {
heights.push(minimum + Math.floor(Math.random() * (maximum - minimum)));
}
if (this.scrollDom) {
const scrollTop = this.scrollDom.scrollTop;
const oldIndex = this.findElementIndex(scrollTop);
const oldHeight = this.state.elementHeights.slice(0, oldIndex).reduce(sum, 0);
const offset = oldHeight - scrollTop;
console.log('oldIndex', oldIndex, 'offset', offset);
const newHeights = heights.slice(0, oldIndex).reduce(sum, 0);
// console.log('oldHeight', oldHeight, 'newHeights', newHeights);
// const diff = newHeights - oldHeight;
// console.log('diff', diff);
// this.scrollDom.scrollTop += diff;
this.scrollDom.scrollTop = Math.max(newHeights - offset, 0);
}
return heights;
},
changeElementHeights: function() {
var newElements = this.generateVariableElementHeights(NUM);
this.setState({
isInfiniteLoading: false,
elementHeights:
// that.state.elementHeights.concat(newElements)
newElements
});
},
handleInfiniteLoad: function() {
this.setState({
isInfiniteLoading: true
});
},
elementInfiniteLoad: function() {
return <div className="infinite-list-item">
Loading...
</div>;
},
findElementIndex: function(scroll) {
const el = this.state.elementHeights;
let sum = 0;
let i;
for (i = 0; i < el.length && sum < scroll; i++) {
sum += el[i];
}
return i;
},
scrolling: function(dom) {
// console.log('scrolling', dom.scrollTop, this.refs.container.refs.scrollable.scrollTop);
console.log('index', dom.scrollTop, this.findElementIndex(dom.scrollTop));
},
render: function() {
var elements = this.state.elementHeights.map(function(el, i) {
return <ListItem key={i} index={i} height={el} lineHeight={el.toString() + "px"}/>;
});
return <Infinite ref="container" elementHeight={this.state.elementHeights}
containerHeight={450}
infiniteLoadBeginEdgeOffset={200}
onInfiniteLoad={this.handleInfiniteLoad}
loadingSpinnerDelegate={this.elementInfiniteLoad()}
timeScrollStateLastsForAfterUserScrolls={1000}
displayBottomUpwards={ true }
handleScroll={this.scrolling }
>
{elements}
</Infinite>;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment