Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
const getDimensions = () => {
const { body } = document;
const doc = document.documentElement;
const scrollTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
const viewportHeight = Math.max(doc.clientHeight, window.innerHeight || 0);
const documentHeight = Math.max(
body.scrollHeight,
body.offsetHeight,
doc.clientHeight,
doc.scrollHeight,
doc.offsetHeight,
);
return {
scrollTop,
viewportHeight,
documentHeight,
};
};
const ScrollContext = React.createContext(getDimensions());
/**
* Context Provider that handles/informs scroll events.
*/
class ScrollProvider extends PureComponent {
state = getDimensions();
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
}
static defaultProps = {
children: null,
};
componentDidMount() {
window.addEventListener('scroll', this.eventListener);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.eventListener);
}
eventListener = () => {
this.setState(getDimensions());
}
render() {
const { children } = this.props;
return (
<ScrollContext.Provider value={this.state}>
{children}
</ScrollContext.Provider>
);
}
}
const withScrolling = TargetComponent => props => (
<ScrollContext.Consumer>
{({
scrollTop,
viewportHeight,
documentHeight,
}) => (
<TargetComponent
{...props}
scrollTop={scrollTop}
viewportHeight={viewportHeight}
documentHeight={documentHeight}
/>
)}
</ScrollContext.Consumer>
);
export { withScrolling };
export default ScrollProvider;
|