forked from polka_billy/porridger
Added useSend hook, converted useFetch to use it
Moved useFetch Related to #19
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import useFetch from './useFetch'
|
||||
import { useFetch } from '../'
|
||||
import { FiltersType } from '../../utils/filters'
|
||||
import { composeAnnouncementsURL, initialAnnouncements, processAnnouncements } from '../../api/announcements'
|
||||
|
||||
|
@ -1,130 +0,0 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { handleHTTPErrors, isAborted } from '../../utils'
|
||||
import { getToken } from '../../utils/auth'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { SetState } from '../../utils/types'
|
||||
|
||||
type UseFetchShared = {
|
||||
loading: boolean,
|
||||
abort?: () => void,
|
||||
}
|
||||
|
||||
type UseFetchSucced<T> = {
|
||||
error: null,
|
||||
data: T,
|
||||
} & UseFetchShared
|
||||
|
||||
type UseFetchErrored = {
|
||||
error: string,
|
||||
data: undefined
|
||||
} & UseFetchShared
|
||||
|
||||
const gotError = <T>(res: UseFetchErrored | UseFetchSucced<T>): res is UseFetchErrored => (
|
||||
typeof res.error === 'string'
|
||||
)
|
||||
|
||||
const fallbackError = <T>(res: UseFetchSucced<T> | UseFetchErrored) => (
|
||||
gotError(res) ? res.error : res.data
|
||||
)
|
||||
|
||||
type UseFetchReturn<T> = ({
|
||||
error: null,
|
||||
data: T
|
||||
} | {
|
||||
error: string,
|
||||
data: undefined
|
||||
}) & {
|
||||
loading: boolean,
|
||||
setData: SetState<T | undefined>
|
||||
abort?: (() => void)
|
||||
}
|
||||
|
||||
const useFetch = <R, T>(
|
||||
url: string,
|
||||
method: RequestInit['method'],
|
||||
needAuth: boolean,
|
||||
guardResponse: (data: unknown) => data is R,
|
||||
processData: (data: R) => T,
|
||||
initialData?: T,
|
||||
params?: RequestInit
|
||||
): UseFetchReturn<T> => {
|
||||
const [data, setData] = useState(initialData)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const abortControllerRef = useRef<AbortController>()
|
||||
|
||||
useEffect(() => {
|
||||
if (abortControllerRef.current) {
|
||||
abortControllerRef.current.abort()
|
||||
}
|
||||
|
||||
const abortController = new AbortController()
|
||||
abortControllerRef.current = abortController
|
||||
|
||||
const headers = new Headers({
|
||||
...params?.headers
|
||||
})
|
||||
|
||||
if (needAuth) {
|
||||
const token = getToken()
|
||||
|
||||
if (token === null) {
|
||||
return navigate('/login')
|
||||
}
|
||||
|
||||
headers.append('Auth', `Bearer ${token}`)
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method,
|
||||
...params,
|
||||
headers,
|
||||
signal: abortControllerRef.current.signal,
|
||||
})
|
||||
.then(res => {
|
||||
handleHTTPErrors(res)
|
||||
|
||||
return res.json()
|
||||
})
|
||||
.then(data => {
|
||||
if (!guardResponse(data)) {
|
||||
throw new Error('Malformed server response')
|
||||
}
|
||||
|
||||
setData(processData(data))
|
||||
setLoading(false)
|
||||
})
|
||||
.catch(err => {
|
||||
if (err instanceof Error && !isAborted(err)) {
|
||||
setError('Ошибка сети')
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(url, params, err)
|
||||
}
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
})
|
||||
|
||||
return () => abortControllerRef.current?.abort()
|
||||
}, [url, method, needAuth, params, guardResponse, processData, navigate])
|
||||
|
||||
return {
|
||||
...(
|
||||
error === null ? ({
|
||||
data: data!, error: null
|
||||
}) : ({ data: undefined, error })
|
||||
),
|
||||
loading,
|
||||
setData,
|
||||
abort: abortControllerRef.current?.abort.bind(abortControllerRef.current)
|
||||
}
|
||||
}
|
||||
|
||||
export default useFetch
|
||||
|
||||
export { gotError, fallbackError }
|
@ -1,6 +1,6 @@
|
||||
import { LatLng } from 'leaflet'
|
||||
|
||||
import useFetch from './useFetch'
|
||||
import { useFetch } from '../'
|
||||
import { composeOsmAddressURL, processOsmAddress } from '../../api/osmAddress'
|
||||
import { isOsmAddressResponse } from '../../api/osmAddress/types'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { LatLng } from 'leaflet'
|
||||
|
||||
import useFetch from './useFetch'
|
||||
import { useFetch } from '../'
|
||||
import { composeTrashboxURL } from '../../api/trashbox'
|
||||
import { isTrashboxResponse } from '../../api/trashbox/types'
|
||||
|
||||
|
Reference in New Issue
Block a user