Source

components/with-lazy.js

  1. import { func, number, string } from 'prop-types';
  2. import React from 'react';
  3. /**
  4. * This component can be used to load some DOM just before it scrolls into the screen. Currently, it does not support unloading. The `margin` prop is passed to `IntersectionObserver`.
  5. *
  6. * Example
  7. * ```javascript
  8. * import { WithLazy } from '@quintype/components';
  9. *
  10. * <WithLazy margin="50px">{() =>
  11. * <SomeHeavyComponent />
  12. * }</WithLazy>
  13. * ```
  14. * @component
  15. * @hideconstructor
  16. * @category Other
  17. */
  18. export class WithLazy extends React.Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = { loaded: false };
  22. this.observerRef = React.createRef();
  23. }
  24. render() {
  25. if (this.state.loaded) {
  26. return this.props.children();
  27. } else {
  28. return <div style={{ height: this.props.height || 50 }} ref={this.observerRef} />;
  29. }
  30. }
  31. componentDidMount() {
  32. this.observer = new global.IntersectionObserver((entries, observer) => this.observerCallback(entries, observer), {
  33. rootMargin: this.props.margin || "160px"
  34. });
  35. this.observer.observe(this.observerRef.current);
  36. }
  37. componentWillUnmount() {
  38. this.observer.disconnect();
  39. }
  40. observerCallback(entries, observer) {
  41. entries.forEach(entry => {
  42. if (entry.isIntersecting || entry.isIntersecting === undefined) {
  43. this.setState({ loaded: true });
  44. observer.disconnect();
  45. }
  46. });
  47. }
  48. }
  49. WithLazy.propTypes = {
  50. children: func.isRequired,
  51. margin: string,
  52. height: number
  53. };