react-infinite-any-height
Version:
Wrapper component for react-infinite which auto calculates element heights.
102 lines (82 loc) • 2.36 kB
JSX
import React, { Component } from "react"
import PropTypes from "prop-types"
import ReactDOM from "react-dom"
import ReactInfinite from "react-infinite"
import isEqual from "lodash.isequal"
import GetHeightWrapper from "./GetHeightWrapper.jsx"
export default class InfiniteAnyHeight extends Component {
static displayName = "InfiniteAnyHeight"
static propTypes = {
"heights": PropTypes.array,
"heightsUpdateCallback": PropTypes.func,
"list": PropTypes.node,
"scrollContainer": PropTypes.object,
"useWindowAsScrollContainer": PropTypes.bool,
}
static defaultProps = {
"heightsUpdateCallback": () => {},
"heights": [],
}
state = {
"heights": [],
"list": [],
}
lastScrollTop = 0
scrollTopDelta = 0
componentDidMount = () => {
this.setList (this.props.list)
}
componentWillReceiveProps = (nextProps) => {
if (!isEqual (nextProps.list, this.props.list)) {
this.setList (nextProps.list)
}
}
getScrollContainer = () => {
if (this.props.useWindowAsScrollContainer) {
return document.body
}
return ReactDOM.findDOMNode (this)
}
addHeight = (i, height) => {
const heights = this.state.heights
const scrollDiff = height - heights[i]
if (scrollDiff && this.scrollTopDelta < 0) {
this.getScrollContainer ().scrollTop += scrollDiff
}
heights[i] = height
this.props.heightsUpdateCallback (heights)
this.setState ({ heights })
}
setList = (listProp) => {
const heights = []
const list = listProp.map ((item, i) => {
heights[i] = this.state.heights[i] || this.props.heights[i] || 200
return (
<GetHeightWrapper
addHeight={(height) => this.addHeight (i, height)}
key={i}
>
{item}
</GetHeightWrapper>
)
})
this.setState ({ heights, list })
}
handleScroll = (...args) => {
const scrollTop = this.getScrollContainer ().scrollTop
this.scrollTopDelta = scrollTop - this.lastScrollTop
this.lastScrollTop = scrollTop
if (typeof this.props.handleScroll === "function") {
this.props.handleScroll (...args)
}
}
render = () => (
<ReactInfinite
elementHeight={this.state.heights}
handleScroll={this.handleScroll}
{...this.props}
>
{this.state.list}
</ReactInfinite>
)
}