Привет, меня зовут Infanty, мой профиль в LinkedIn.
Я пишу how-to статьи на редкие темы или статьи обзоры - для себя и тех кто со мной работает.

Пример класса для асинхронного получения данных с сервера используя axios:

class DataService {
  // Функция генерации уникального идентификатора (GUID).
  guid() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1)
    }

    return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`
  }

  // Функция получения данных.
  async getData(entityId) {
    // Инициализация HTTP клиента.
    let axios = require('axios')
    // Построение URL из данных переменной окружения
    // и данных переданных с помощью переменной в функцию.
    let url = `${process.env.REACT_APP_URL}/${entityId}`
    // Инициализация строки идентификации (для примера - вместо
    // функции получения токена использована функция получения GUID.
    let authStr = 'Bearer '.concat(this.guid())
    // Инициализация строки для идентификации данного запроса в
    // логах сервера используя заголовок: X-Correlation-Id.
    let xCorrelationId = this.guid()

    try {
      // Асинхронное получение JSON данных.
      const getData = await axios.get(url, {
        headers: {
          Authorization: authStr,
          'X-Correlation-Id': xCorrelationId,
          'Content-Type': 'application/json',
        },
      })

      // Если в полученных данных отсутствует объект: pageType.
      if (typeof getData.data.pageType === undefined) {
        // Возврат заранее определённых данных, в случае
        // не получения валидных данных с сервера.
        this.data = {
          pageType: 'error',
          fileSize: 0,
          dataDescription: '',
        }

        return this.data
      }

      // Заполнение pageType в возвращаемых данных - на основе соответствующих
      // данных из ответа сервера, при их наличии. При их отсутствии в
      // pageType будет помещена пустая строка. Так же если в ответе сервера
      // pageType будет отличного от определённого в массиве this.state,
      // то pageType будет помещена пустая строка.
      this.data.pageType = this.tryGetValueOrEmptyString(
        this.state[this.tryGetValueOrEmptyString(getData.data.state)]
      )

      // Заполнение fileSize в возвращаемых данных - соответствующими
      // данными из ответа сервера, при их наличии в составе объекта
      // file - который должен так же присутствовать в данных ответа сервера.
      // При их отсутствии в fileSize будет помещена пустая строка.
      this.data.fileSize = this.tryGetValueOrEmptyString(
        getData.data.file && getData.data.file.size
      )
      // Замена пустой строки в fileSize на ноль - вынесена в отдельную
      // строку, для упрощения конструкции.
      if (this.data.fileSize === '') this.data.fileSize = 0

      // Заполнение dataDescription в возвращаемых данных - соответствующими
      // данными из ответа сервера, при их наличии. При их отсутствии в
      // dataDescription будет помещена пустая строка.
      this.data.dataDescription = this.tryGetValueOrEmptyString(
        getData.data.description
      )

      return this.data
    } catch (err) {
      // В случае если код ответа был 401.
      if (err.response.status === 401) {
        // Регенерация токена.
        // ...

        // Возврат данных о том, что необходимо
        // перезапустить получение данных.
        return this.data
      } else {
        // В случае если код ответа был отличный от 200 и 401.
        // Возврат заранее определённых данных.
        this.data = {
          pageType: 'error',
          fileSize: 0,
          dataDescription: '',
        }

        return this.data
      }
    }
  }

  // Функция возвращает значение при его существовании
  // или возвращает пустую строку.
  tryGetValueOrEmptyString(variableToCheck) {
    return typeof variableToCheck !== undefined ? variableToCheck : ''
  }

  // Инициализация класса.
  constructor() {
    // Инициализация возвращаемых данных.
    this.data = {
      pageType: '',
      fileSize: 0,
      dataDescription: '',
    }

    // Массив для преобразования pageType из данных ответа
    // сервера - в нужный pageType приложения.
    this.state = {
      Failed: 'processed-error',
      Processed: 'processed',
      Processing: 'processing',
      Initializing: 'processing',
    }
  }
}

export default new DataService()

Пример класса использующего класс для асинхронного получения данных с сервера используя axios:

import React from 'react'
import dataService from '../../services/dataService'
import PropTypes from 'prop-types'

class pageDetail extends React.Component {
  // Конструктор класса.
  constructor(props) {
    // Вызов родительского конструктора класса.
    super(props)

    // Стартовые значения набора переменных состояния класса.
    this.state = {
      pageType: 'loading',
      fileSize: 0,
      dataDescription: '',
    }
  }

  // Функция вызывается сразу после монтирования 
  // компонента (в DOM дерево).
  componentDidMount() {
    // Вариант 1: Единоразовое асинхронное получение данных.
    this.dataServiceGetData()

    // Вариант 2: Запуск асинхронного обновления данных
    // через заданный промежуток времени.
    this.rundataServiceGetData()
  }

  // Функция синхронного обновления данных
  // через заданный промежуток времени.
  rundataServiceGetData() {
    // Первое асинхронное получение данных в варианте 2.
    this.dataServiceGetData()

    // Запуск таймера для асинхронного обновления данных.
    var isThis = this
    setTimeout(function tick() {
      // Если перед этим не полученны данные в которых
      // pageType равен: error.
      if (isThis.state.pageType !== 'error') {
        // Асинхронное обновление данных.
        isThis.dataServiceGetData()

        // Перезапуск таймера через 5 секунд.
        setTimeout(tick, 5000)
      }
    }, 5000)
  }

  // Асинхронное обновление данных.
  async dataServiceGetData() {
    // Запуск асинхронного получения данных используя axios 
    // и ID переданное в компонент.
    let data = await dataService.getData(this.props.entityId)

    // Обновление набора переменных состояния класса производится
    // только если полученные данные отличаются от текущих.
    if (
      data.pageType !== this.state.pageType ||
      data.fileSize !== this.state.fileSize ||
      data.dataDescription !== this.state.dataDescription
    ) {
      this.setState({ ...data })
    }
  }

  ...
  ...
  ...
}

pageDetail.propTypes = {
  entityId: PropTypes.string,
}

export default pageDetail