Small React component for implementing infinity scroll
I've created a demo with create-react-app so you can see my component in action. The source can be found in gh-pages branch, don't judge me, please, I was in a hurry.
Demo: https://khorolets.github.io/react-infinity-scroll/
$ npm install react-infinity-scroll --save
import React from 'react'
import Review from '../components/review_critics'
import InfinityScroll from 'react-infinity-scroll'
import { getCriticsReviews } from '../actions/media'
export default class extends React.Component {
constructor(props) {
super(props)
this.state = {
'reviews': [],
'hasMore': false,
}
}
componentWillMount() {
getCriticsReviews(1)
.then(
(res) => {
this.setState({
reviews: res.data.results.map((review) => (<Review title={review.title} />))
})
}
)
}
loadMore = (page, callback = undefined) => {
getCriticsReviewsByCriticId(page).then((res) => {
this.setState(
{
reviews: [
...this.state.reviews,
res.data.results.map((review) => (<Review title={review.title} />))
],
hasMore: (res.data.next)
},
() => {
if (callback !== undefined) {
callback()
}
}
)
})
}
render() {
return (
<InfinityScroll
pageStart={1}
bottomOffset={250}
loadMore={this.loadMore}
hasMore={this.state.hasMore}
loader={<div className="loader">Loading ...</div>}
>
{this.state.reviews}
</InfinityScroll>
)
}
}If you need to use InfinityScroll in modal or other div which is scrollable you need to listen that scroll instead of default window one.
InfinityScroll won't add listeners to window if you provide bottomOffsetValue which is representing current distance to the bottom of the element.
So you need manually to:
- Add listener to an element that has a scroll you're interested in.
componentDidMount() {
document.getElementsByClassName('vmodal-wrapper')[0]
.addEventListener('scroll', this._calculateOffset)
}
componentWillUnmount() {
document.getElementsByClassName('vmodal-wrapper')[0]
.removeEventListener('scroll', this._calculateOffset)
}- Create a method that calculates current offset
_calculateOffset = () => {
const modalWrapper = document.getElementsByClassName('vmodal-wrapper')[0]
const modalBody = document.getElementsByClassName('vmodal-body')[0]
return this.setState(
{
bottomOffsetValue: modalBody.offsetHeight - modalWrapper.scrollTop,
}
)
}- Pass that method to
InfinityScroll
<InfinityScroll
pageStart={1}
bottomOffset={1000}
bottomOffsetValue={this.state.bottomOffsetValue}
loadMore={this.props.loadMore}
hasMore={this.props.hasMore}
loader={<div className="text-center loader">Loading...</div>}
>
...
</InfinityScroll>That's it.
- React 8 (infinity) https://www.npmjs.com/package/react-8
- react-infinity-scroller https://www.npmjs.com/package/react-infinity-scroller