digitalfabrik/integreat-app

View on GitHub
native/src/hooks/useLoadCities.ts

Summary

Maintainability
A
1 hr
Test Coverage
F
34%
import { useCallback } from 'react'

import { CityModel, createCitiesEndpoint, ReturnType, useLoadAsync, fromError } from 'shared/api'

import { SnackbarType } from '../components/SnackbarContainer'
import dataContainer from '../utils/DefaultDataContainer'
import { determineApiUrl } from '../utils/helpers'
import useSnackbar from './useSnackbar'

const loadWithCache = async ({
  showSnackbar,
  forceUpdate = false,
}: {
  forceUpdate?: boolean
  showSnackbar: (snackbar: SnackbarType) => void
}): Promise<CityModel[] | null> => {
  const cachedData = (await dataContainer.citiesAvailable()) ? await dataContainer.getCities() : null

  if (!forceUpdate && cachedData) {
    return cachedData
  }

  try {
    const payload = await createCitiesEndpoint(await determineApiUrl()).request()
    if (payload.data) {
      await dataContainer.setCities(payload.data)
    }
    return payload.data ?? cachedData
  } catch (e) {
    if (!cachedData) {
      throw e
    }
    if (forceUpdate) {
      showSnackbar({ text: fromError(e) })
    }
  }
  return cachedData
}

const useLoadCities = (): ReturnType<CityModel[]> => {
  const showSnackbar = useSnackbar()
  return useLoadAsync(useCallback(forceUpdate => loadWithCache({ showSnackbar, forceUpdate }), [showSnackbar]))
}

export default useLoadCities