Skip to content

Instantly share code, notes, and snippets.

@sandwichsudo
Last active July 16, 2019 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sandwichsudo/5a60c87b9990c0aef6657e476262f6eb to your computer and use it in GitHub Desktop.
Save sandwichsudo/5a60c87b9990c0aef6657e476262f6eb to your computer and use it in GitHub Desktop.
React Infinite scroll component (design for use with ApolloClient/Relay Pagination)
/**
* Credit: https://medium.com/@alfianlosari/graphql-cursor-infinite-scroll-pagination-with-react-apollo-client-and-github-api-fafbc510b667
* This component will call the onLoadMore prop when you scroll to the bottom of the page or click
* the button, and pass the fetched data to the component you give it
* */
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
class InfiniteScroll extends Component {
constructor(props) {
super(props);
this.handleOnScroll = this.handleOnScroll.bind(this);
}
componentDidMount() {
window.addEventListener('scroll', this.handleOnScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleOnScroll);
}
handleOnScroll() {
// http://stackoverflow.com/questions/9439725/javascript-how-to-detect-if-browser-window-is-scrolled-to-bottom
const scrollTop =
(document.documentElement && document.documentElement.scrollTop) ||
document.body.scrollTop;
const scrollHeight =
(document.documentElement &&
document.documentElement.scrollHeight) ||
document.body.scrollHeight;
const clientHeight =
document.documentElement.clientHeight || window.innerHeight;
const scrolledToBottom =
Math.ceil(scrollTop + clientHeight) >= scrollHeight;
if (scrolledToBottom && this.props.hasNextPage) {
this.props.onLoadMore();
}
}
render() {
const {
error,
loading,
RenderComponent,
data,
onLoadMore,
hasNextPage,
} = this.props;
return (
<Fragment>
<RenderComponent error={error} loading={loading} {...data} />
<div className="container-fluid--limit">
<button
disabled={!hasNextPage}
className="button-small"
onClick={onLoadMore}
>
Load more
</button>
</div>
</Fragment>
);
}
}
InfiniteScroll.propTypes = {
// any error that happened while fetching data
error: PropTypes.string,
// whether we are loading data or not
loading: PropTypes.bool,
// the component to pass the loaded data to
RenderComponent: PropTypes.func.isRequired,
// the loaded data to pass to the component
data: PropTypes.object,
};
export default InfiniteScroll;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment