barinbritva
2/7/2017 - 2:50 PM

AbstractContainer.tsx

import React = require('react');

import AnyCancellablePromise = require('../interface/AnyCancellablePromise');
import AbstractContainerPropsInterface = require('./AbstractContainerPropsInterface');
import PreloaderComponent = require('./PreloaderComponent');
import ErrorHandlerComponent = require('./ErrorHandlerComponent');

abstract class AbstractContainer<P extends AbstractContainerPropsInterface, S> extends React.Component<P, S> {
  protected requestList: AnyCancellablePromise[] = [];

  public componentDidMount(): void {
    this.doAfterMount();
    this.fetchData();
  }

  public componentWillUnmount(): void {
    this.doBeforeUnmount();
    this.cancelAllRequests();
  }

  protected addRequest(promise: AnyCancellablePromise): void {
    this.requestList.push(promise);
  }

  protected abstract doAfterMount(): void;

  protected abstract doBeforeUnmount(): void;

  protected abstract fetchData(): void;

  protected abstract renderContent(): JSX.Element;

  private cancelAllRequests(): void {
    this.requestList.map(
      (promise: AnyCancellablePromise) => {
        promise.cancel();
      }
    );
  }

  public render(): JSX.Element {
    if (this.requestList.length > 0) {
      return this.props.loaderComponent || <PreloaderComponent />;
    }

    try {
      return this.renderContent();
    } catch (error) {
      return this.props.errorHandlerComponent || <ErrorHandlerComponent />;
    }
  }
}

export = AbstractContainer;