Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Created December 16, 2015 16:40
Show Gist options
  • Save ryanflorence/05302c52e53a68eceb4c to your computer and use it in GitHub Desktop.
Save ryanflorence/05302c52e53a68eceb4c to your computer and use it in GitHub Desktop.
import React from 'react'
const { number, func, array, shape } = React.PropTypes
export default React.createClass({
propTypes: {
itemHeight: number.isRequired,
renderItem: func.isRequired,
items: array.isRequired,
style: shape({
height: number.isRequired
}).isRequired,
buffer: number.isRequired
},
getDefaultProps() {
return { buffer: 20 }
},
getInitialState() {
return { scrollTop: 0 }
},
render() {
const { itemHeight, renderItem, items, style, buffer } = this.props
const { scrollTop } = this.state
const { height } = style
const scrollableHeight = items.length * itemHeight
const firstIndex = Math.floor(scrollTop/itemHeight)
const lastIndex = Math.floor(height/itemHeight) + firstIndex
const bufferedFirst = firstIndex < buffer ? 0 : firstIndex - buffer
const bufferedLast = lastIndex + buffer
const visibleItems = items.slice(bufferedFirst, bufferedLast)
return (
<div
{...this.props}
style={{ ...style, height, overflow: 'auto' }}
onScroll={(event) => {
this.setState({
scrollTop: event.target.scrollTop
})
}}
>
<div style={{
height: scrollableHeight
}}>
<div style={{
transform: `translate3d(0, ${bufferedFirst * itemHeight}px, 0)`
}}>
{visibleItems.map((item, index) => (
renderItem(item, index + bufferedFirst, index)
))}
</div>
</div>
</div>
)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment