* * @param {RequestInfo} resource * @param {RequestInit} init * @param {FetchOptions} options * @returns {AsyncState >}
(
resource: RequestInfo,
init: RequestInit,
{ defer, json, ...options }: FetchOptions<T> = {}
)
| 283 | * @returns {AsyncState<T, FetchRun<T>>} |
| 284 | */ |
| 285 | function useAsyncFetch<T>( |
| 286 | resource: RequestInfo, |
| 287 | init: RequestInit, |
| 288 | { defer, json, ...options }: FetchOptions<T> = {} |
| 289 | ): AsyncState<T, FetchRun<T>> { |
| 290 | const method = (resource as Request).method || (init && init.method) |
| 291 | const headers: Headers & Record<string, any> = |
| 292 | (resource as Request).headers || (init && init.headers) || {} |
| 293 | const accept: string | undefined = |
| 294 | headers["Accept"] || headers["accept"] || (headers.get && headers.get("accept")) |
| 295 | const doFetch = (input: RequestInfo, init: RequestInit) => |
| 296 | globalScope.fetch(input, init).then(parseResponse(accept, json)) |
| 297 | const isDefer = |
| 298 | typeof defer === "boolean" ? defer : ["POST", "PUT", "PATCH", "DELETE"].indexOf(method!) !== -1 |
| 299 | const fn = isDefer ? "deferFn" : "promiseFn" |
| 300 | const identity = JSON.stringify({ |
| 301 | resource, |
| 302 | init, |
| 303 | isDefer, |
| 304 | }) |
| 305 | const promiseFn = useCallback( |
| 306 | (_: AsyncOptions<T>, { signal }: AbortController) => { |
| 307 | return doFetch(resource, { signal, ...init }) |
| 308 | }, |
| 309 | [identity] // eslint-disable-line react-hooks/exhaustive-deps |
| 310 | ) |
| 311 | const deferFn = useCallback( |
| 312 | function([override]: FetchRunArgs, _: AsyncOptions<T>, { signal }: AbortController) { |
| 313 | if (!override || isEvent(override)) { |
| 314 | return doFetch(resource, { signal, ...init }) |
| 315 | } |
| 316 | if (typeof override === "function") { |
| 317 | const { resource: runResource, ...runInit } = override({ resource, signal, ...init }) |
| 318 | return doFetch(runResource || resource, { signal, ...runInit }) |
| 319 | } |
| 320 | const { resource: runResource, ...runInit } = override |
| 321 | return doFetch(runResource || resource, { signal, ...init, ...runInit }) |
| 322 | }, |
| 323 | [identity] // eslint-disable-line react-hooks/exhaustive-deps |
| 324 | ) |
| 325 | const state = useAsync({ |
| 326 | ...options, |
| 327 | [fn]: isDefer ? deferFn : promiseFn, |
| 328 | }) |
| 329 | useDebugValue(state, ({ counter, status }) => `[${counter}] ${status}`) |
| 330 | return state |
| 331 | } |
| 332 | |
| 333 | const unsupported = () => { |
| 334 | throw new Error( |