All files / src simpleImgProvider.js

100% Statements 17/17
100% Branches 5/5
100% Functions 10/10
100% Lines 17/17
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102          2x                                                                     10x   10x 6x   4x 1x 1x               1x   1x       1x       3x 3x 3x 3x             1x       1x       17x                                    
// @flow
import React from 'react';
import observerStart, { defaultConfig } from './logic/observerStart';
 
// $FlowIgnoreLine:
export const SimpleImgContext = React.createContext({});
 
type State = {
  mountedImages: Set<any>,
  isContextDocumentLoad: boolean,
};
 
export type Config = {
  root?: HTMLElement,
  rootMargin?: string,
  threshold?: number | Array<number>,
};
 
type Props = {
  config?: Object,
  children: any,
};
 
export default class SimpleImgProvider extends React.Component<Props, State> {
  static displayName = 'SimpleImgProvider';
 
  static defaultProps = {
    config: defaultConfig,
  };
 
  state: State = {
    mountedImages: new Set(),
    isContextDocumentLoad: false,
  };
 
  observer = {};
 
  imageLoadRefs: Set<any> = new Set();
 
  componentDidMount() {
    const { config } = this.props;
 
    if (document.readyState === 'complete') {
      this.observer = observerStart.call(this, config);
    } else {
      window.addEventListener('load', () => {
        this.observer = observerStart.call(this, config);
        this.setState({
          isContextDocumentLoad: true,
        });
      });
    }
  }
 
  componentWillUnmount() {
    this.imageLoadRefs.forEach(image => {
      // cancel all loading images;
      image.src = ''; // eslint-disable-line no-param-reassign
    });
  }
 
  appendImageRef = (image: HTMLElement) => this.observer && this.observer.observe && this.observer.observe(image);
 
  removeImageRef = (image: HTMLElement) => {
    // $FlowIgnoreLine:
    this.observer.unobserve(image);
    this.setState(({ mountedImages }) => {
      mountedImages.delete(image);
      return {
        mountedImages,
      };
    });
  };
 
  appendImgLoadingRef = (image: HTMLElement) => {
    this.imageLoadRefs.add(image);
  };
 
  removeImgLoadingRef = (image: HTMLElement) => {
    this.imageLoadRefs.delete(image);
  };
 
  render() {
    return (
      <SimpleImgContext.Provider
        value={{
          ...{
            ...this.state,
            useContext: true,
            appendImageRef: this.appendImageRef,
            removeImageRef: this.removeImageRef,
            appendImgLoadingRef: this.appendImgLoadingRef,
            removeImgLoadingRef: this.removeImgLoadingRef,
          },
        }}
      >
        {this.props.children}
      </SimpleImgContext.Provider>
    );
  }
}