import { Dispatch , SetStateAction } from 'react' ; import { FetchState } from './types' ; import isJSON from './isJSON' ; const fetchData = async < T > ( url , init = { } , controller , setState ) : Promise < void > => { const actualInit = { ... init , signal : controller . signal } ; let rsp = null ; try { setState ( ( oldState ) : FetchState < T > => ( { data : null , loading : oldState . loading + 1 , error : null , controller } ) ) ; rsp = await fetch ( url , actualInit ) ; const contentTypeHeader = rsp . headers . get ( 'content-type' ) ; if ( contentTypeHeader ) { let data = null ; if ( isJSON ( contentTypeHeader ) ) { data = await rsp . json ( ) ; } else { data = await rsp . text ( ) ; } setState ( ( oldState ) : FetchState < T > => ( { ... oldState , data , loading : oldState . loading - 1 } ) ) ; } else { setState ( ( oldState ) : FetchState < T > => ( { ... oldState , loading : oldState . loading - 1 } ) ) ; } if ( ! rsp . ok ) { const err = new Error ( rsp . statusText ) ; err . status = rsp . status ; throw err ; } } catch ( e ) { const err = e ; const error = err . name !== 'AbortError' ? err : null ; setState ( ( oldState ) : FetchState < T > => ( { ... oldState , error , loading : rsp ? oldState . loading : oldState . loading - 1 } ) ) ; } } ; export default fetchData ;