From d874d0ceb8b3e30fdbd58fe33716ebdd83066717 Mon Sep 17 00:00:00 2001 From: danybeltran Date: Sun, 8 Dec 2024 14:29:40 -0600 Subject: [PATCH 1/2] enh(server): Prevents unexpected side effects by avoiding setting global cache server side --- package.json | 2 +- src/components/FetchConfigAsync.tsx | 45 +++++++++-------------------- src/components/index.tsx | 34 +++++++++++++--------- src/components/server/index.tsx | 10 +++---- src/hooks/use-fetch.ts | 7 ++++- 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 2cb7608..6fb3e6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-react", - "version": "3.7.2", + "version": "3.7.3", "description": "React hooks for data fetching", "main": "dist/index.js", "scripts": { diff --git a/src/components/FetchConfigAsync.tsx b/src/components/FetchConfigAsync.tsx index d75ac72..1387ccd 100644 --- a/src/components/FetchConfigAsync.tsx +++ b/src/components/FetchConfigAsync.tsx @@ -1,55 +1,37 @@ -import { isDefined, serialize } from '../client' -import { - defaultCache, - fetcherDefaults, - valuesMemory, - willSuspend -} from '../internal' +import { isDefined } from '../client' import { $context } from '../internal/shared' import { FetchContextType } from '../types' +import { FetchConfigSync } from './server' export async function FetchConfigAsync(props: FetchContextType) { - const { children, defaults = {}, value = {}, suspense = [] } = props + const { children, defaults = {}, value = {} } = props + + let $values = new Map() const previousConfig = $context.value as any - const { cacheProvider = defaultCache } = previousConfig for (let valueKey in value) { - const resolvedKey = serialize({ - idString: serialize(valueKey) - }) - const $value = await value[valueKey] const $data = $value.data ?? $value - valuesMemory.set(resolvedKey, $data) + $values.set(valueKey, $data) - fetcherDefaults.set(resolvedKey, $data) + // fetcherDefaults.set(resolvedKey, $data) - cacheProvider.set(resolvedKey, $data) + // cacheProvider.set(resolvedKey, $data) } for (let defaultKey in defaults) { const { id = defaultKey } = defaults[defaultKey] - const resolvedKey = serialize({ - idString: serialize(id) - }) if (isDefined(id)) { - valuesMemory.set(resolvedKey, await defaults[defaultKey]?.value) - fetcherDefaults.set(resolvedKey, await defaults[defaultKey]?.value) - cacheProvider.set(resolvedKey, await defaults[defaultKey]?.value) + $values.set(defaultKey, await defaults[defaultKey]?.value) + // fetcherDefaults.set(resolvedKey, await defaults[defaultKey]?.value) + // cacheProvider.set(resolvedKey, await defaults[defaultKey]?.value) } } - for (let suspenseKey of suspense) { - const key = serialize({ - idString: serialize(suspenseKey) - }) - willSuspend.set(key, true) - } - let mergedConfig = { ...previousConfig, ...props, @@ -57,10 +39,9 @@ export async function FetchConfigAsync(props: FetchContextType) { ...previousConfig.headers, ...props.headers }, + value: Object.fromEntries($values.entries()), children: undefined } - $context.value = mergedConfig - - return children + return {children} } diff --git a/src/components/index.tsx b/src/components/index.tsx index 1b80a3d..2e8b5f0 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -12,7 +12,7 @@ import { import { FetchContextType } from '../types' -import { isDefined, serialize } from '../utils/shared' +import { isDefined, serialize, windowExists } from '../utils/shared' let isServer: boolean = true /** @@ -39,18 +39,16 @@ export function SSRSuspense({ } export function FetchConfig(props: FetchContextType) { - const { - children, - defaults = {}, - value = {}, - suspense = [], - clientOnly - } = props + const { children, defaults = {}, value: $val = {}, suspense = [] } = props + + const value = (windowExists ? $val : $val.value) ?? {} const previousConfig = useHRFContext() const { cacheProvider = defaultCache } = previousConfig + const $values = new Map() + for (let valueKey in value) { const resolvedKey = serialize({ idString: serialize(valueKey) @@ -77,11 +75,15 @@ export function FetchConfig(props: FetchContextType) { parsedChunk = dataChunk } - valuesMemory.set(resolvedKey, parsedChunk) + $values.set(resolvedKey, parsedChunk) + + if (windowExists) { + valuesMemory.set(resolvedKey, parsedChunk) - fetcherDefaults.set(resolvedKey, parsedChunk) + fetcherDefaults.set(resolvedKey, parsedChunk) - cacheProvider.set(resolvedKey, parsedChunk) + cacheProvider.set(resolvedKey, parsedChunk) + } } for (let defaultKey in defaults) { @@ -91,9 +93,12 @@ export function FetchConfig(props: FetchContextType) { }) if (isDefined(id)) { - valuesMemory.set(resolvedKey, defaults[defaultKey]?.value) - fetcherDefaults.set(resolvedKey, defaults[defaultKey]?.value) - cacheProvider.set(resolvedKey, defaults[defaultKey]?.value) + $values.set(resolvedKey, defaults[defaultKey]?.value) + if (windowExists) { + valuesMemory.set(resolvedKey, defaults[defaultKey]?.value) + fetcherDefaults.set(resolvedKey, defaults[defaultKey]?.value) + cacheProvider.set(resolvedKey, defaults[defaultKey]?.value) + } } } @@ -111,6 +116,7 @@ export function FetchConfig(props: FetchContextType) { ...previousConfig.headers, ...props.headers }, + value: Object.fromEntries($values.entries()), children: undefined } diff --git a/src/components/server/index.tsx b/src/components/server/index.tsx index 08041ce..94c23a1 100644 --- a/src/components/server/index.tsx +++ b/src/components/server/index.tsx @@ -1,9 +1,9 @@ -'use client' +"use client" -import { FetchConfigAsync } from '../FetchConfigAsync' +import { FetchConfigAsync } from "../FetchConfigAsync" -import { FetchConfig as FConfig, SSRSuspense } from '../index' +import { FetchConfig as FConfig, SSRSuspense } from "../index" -const FetchConfig = typeof window === 'undefined' ? FetchConfigAsync : FConfig +const FetchConfig = typeof window === "undefined" ? FetchConfigAsync : FConfig -export { FetchConfig, SSRSuspense } +export { FetchConfig, SSRSuspense, FConfig as FetchConfigSync } diff --git a/src/hooks/use-fetch.ts b/src/hooks/use-fetch.ts index 3ca4f47..526872b 100644 --- a/src/hooks/use-fetch.ts +++ b/src/hooks/use-fetch.ts @@ -101,6 +101,8 @@ export function useFetch( } } + const valueMap = new Map(Object.entries(ctx.value || {})) + const formRef = useRef(null) // @ts-ignore @@ -346,7 +348,10 @@ export function useFetch( const requestCache = cacheProvider.get(resolvedDataKey) - const initialDataValue = valuesMemory.get(resolvedKey) ?? requestCache ?? def + const defaultFromContext = valueMap.get(resolvedKey) + + const initialDataValue = + valuesMemory.get(resolvedKey) ?? requestCache ?? defaultFromContext ?? def const hasInitialOrFallbackData = isDefined(initialDataValue) From 311980873c4fb039513e1571908050d77627d596 Mon Sep 17 00:00:00 2001 From: danybeltran Date: Sun, 8 Dec 2024 14:35:32 -0600 Subject: [PATCH 2/2] fix: Fixes runtime map error --- src/hooks/use-fetch.ts | 384 ++++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 192 deletions(-) diff --git a/src/hooks/use-fetch.ts b/src/hooks/use-fetch.ts index 526872b..033c28e 100644 --- a/src/hooks/use-fetch.ts +++ b/src/hooks/use-fetch.ts @@ -1,5 +1,5 @@ -'use client' -import { useState, useEffect, useMemo, useRef, useCallback } from 'react' +"use client" +import { useState, useEffect, useMemo, useRef, useCallback } from "react" import { abortControllers, @@ -29,10 +29,10 @@ import { suspenseRevalidationStarted, onlineHandled, offlineHandled, - hasData -} from '../internal' + hasData, +} from "../internal" -import { DEFAULT_RESOLVER, METHODS } from '../internal/constants' +import { DEFAULT_RESOLVER, METHODS } from "../internal/constants" import { CustomResponse, @@ -41,16 +41,16 @@ import { FetchContextType, HTTP_METHODS, ImperativeFetch, - TimeSpan -} from '../types' + TimeSpan, +} from "../types" import { createImperativeFetch, getMiliseconds, getTimePassed, revalidate, - useIsomorphicLayoutEffect -} from '../utils' + useIsomorphicLayoutEffect, +} from "../utils" import { createRequestFn, getRequestHeaders, @@ -63,16 +63,16 @@ import { queue, serialize, setURLParams, - windowExists -} from '../utils/shared' -import { $context } from '../internal/shared' + windowExists, +} from "../utils/shared" +import { $context } from "../internal/shared" /** * Passing `undefined` to `new Date()` returns `Invalid Date {}`, so return null instead */ const getDateIfValid = (d: Date | null) => // @ts-ignore - Evals to a Date - (d?.toString() === 'Invalid Date' || d === null ? null : d) as Date + (d?.toString() === "Invalid Date" || d === null ? null : d) as Date /** * Termporary form data is set with the submit method in useFetch and is deleted immediately after resolving (see line #858) @@ -93,15 +93,15 @@ export function useFetch( ...$ctx, query: { ...$context?.value?.query, - ...$ctx?.query + ...$ctx?.query, }, headers: { ...$context.value?.headers, - ...$ctx?.headers - } + ...$ctx?.headers, + }, } - const valueMap = new Map(Object.entries(ctx.value || {})) + const valueMap = new Map(Object.entries(ctx.value ?? {})) const formRef = useRef(null) @@ -109,18 +109,18 @@ export function useFetch( const isRequest = init instanceof Object && init?.json const optionsConfig = - typeof init === 'string' + typeof init === "string" ? { // Pass init as the url if init is a string url: init, - ...options + ...options, } : isRequest ? { url: init.url, method: init.method, init, - ...options + ...options, } : (init as FetchConfigType) @@ -129,14 +129,14 @@ export function useFetch( onOffline = ctx.onOffline, onMutate, revalidateOnMount = ctx.revalidateOnMount, - url = '', + url = "", query = {}, params = {}, baseUrl = undefined, method = isRequest ? init.method : (METHODS.GET as HTTP_METHODS), headers = {} as Headers, body = undefined as unknown as Body, - formatBody = e => JSON.stringify(e), + formatBody = (e) => JSON.stringify(e), resolver = isFunction(ctx.resolver) ? ctx.resolver : DEFAULT_RESOLVER, onError, auto = isDefined(ctx.auto) ? ctx.auto : true, @@ -154,7 +154,7 @@ export function useFetch( cacheIfError = ctx.cacheIfError, maxCacheAge = ctx.maxCacheAge, fetcher = ctx.fetcher, - middleware = ctx.middleware + middleware = ctx.middleware, } = optionsConfig const $fetch = isFunction(fetcher) @@ -170,7 +170,7 @@ export function useFetch( method, headers, body, - formatBody + formatBody, } const { cacheProvider: $cacheProvider = defaultCache } = ctx @@ -180,7 +180,7 @@ export function useFetch( const { cacheProvider = $cacheProvider } = optionsConfig - const requestCallId = useMemo(() => `${Math.random()}`.split('.')[1], []) + const requestCallId = useMemo(() => `${Math.random()}`.split(".")[1], []) const willResolve = isDefined(onResolve) const handleError = isDefined(onError) @@ -198,24 +198,24 @@ export function useFetch( const reqQuery = { ...ctx.query, - ...config.query + ...config.query, } const reqParams = { ...ctx.params, - ...config.params + ...config.params, } const rawUrl = (hasBaseUrl(url) - ? '' + ? "" : !isDefined(config.baseUrl) ? !isDefined(ctx.baseUrl) - ? '' + ? "" : ctx.baseUrl : config.baseUrl) + url - const defaultId = [method, url].join(' ') + const defaultId = [method, url].join(" ") const { id = defaultId } = optionsConfig @@ -234,22 +234,22 @@ export function useFetch( const resolvedDataKey = serialize({ idString, reqQuery, reqParams }) - const ageKey = ['max-age', resolvedDataKey].join('-') + const ageKey = ["max-age", resolvedDataKey].join("-") const paginationCache = cacheProvider.get(resolvedDataKey) const normalCache = cacheProvider.get(resolvedKey) - const maxAge = getMiliseconds(maxCacheAge || '0 ms') + const maxAge = getMiliseconds(maxCacheAge || "0 ms") // Revalidates if passed maxCacheAge has changed - if (!cacheProvider.get('maxAgeValue' + resolvedDataKey)) { - cacheProvider.set('maxAgeValue' + resolvedDataKey, maxCacheAge || '0 ms') + if (!cacheProvider.get("maxAgeValue" + resolvedDataKey)) { + cacheProvider.set("maxAgeValue" + resolvedDataKey, maxCacheAge || "0 ms") } else { - if (cacheProvider.get('maxAgeValue' + resolvedDataKey) !== maxCacheAge) { + if (cacheProvider.get("maxAgeValue" + resolvedDataKey) !== maxCacheAge) { cacheProvider.set(ageKey, 0) - cacheProvider.set('maxAgeValue' + resolvedDataKey, maxCacheAge) + cacheProvider.set("maxAgeValue" + resolvedDataKey, maxCacheAge) } } @@ -271,7 +271,7 @@ export function useFetch( const suspense = $suspense || willSuspend.get(resolvedKey) if (!suspense) { - if (url !== '') { + if (url !== "") { suspenseInitialized.set(resolvedKey, true) } } @@ -284,17 +284,17 @@ export function useFetch( const realUrl = urlWithParams + - (urlWithParams.includes('?') ? (optionsConfig?.query ? `&` : '') : '?') + (urlWithParams.includes("?") ? (optionsConfig?.query ? `&` : "") : "?") if (!previousProps.has(resolvedKey)) { - if (url !== '') { + if (url !== "") { previousProps.set(resolvedKey, optionsConfig) } } const configUrl = urls[resolvedKey] || { realUrl, - rawUrl + rawUrl, } const stringDeps = serialize( @@ -316,7 +316,7 @@ export function useFetch( useEffect(() => { if (isDefined(optionsConfig.default)) { if (!fetcherDefaults.has(resolvedKey)) { - if (url !== '') { + if (url !== "") { if (!isDefined(cacheProvider.get(resolvedDataKey))) { fetcherDefaults.set(resolvedKey, optionsConfig.default) } @@ -324,7 +324,7 @@ export function useFetch( if (!isDefined(cacheProvider.get(resolvedDataKey))) { requestsProvider.emit(resolvedKey, { requestCallId, - data: optionsConfig.default + data: optionsConfig.default, }) } } @@ -362,16 +362,16 @@ export function useFetch( ? isPending(resolvedKey) || (revalidateOnMount ? !jsonCompare( - JSON.parse(previousConfig.get(resolvedKey) || '{}'), + JSON.parse(previousConfig.get(resolvedKey) || "{}"), optionsConfig ) : !jsonCompare( - JSON.parse(previousConfig.get(resolvedKey) || '{}'), + JSON.parse(previousConfig.get(resolvedKey) || "{}"), optionsConfig )) : false, error: (hasErrors.get(resolvedDataKey) || false) as boolean, - completedAttempts: 0 + completedAttempts: 0, }) const thisDeps = useRef({ @@ -379,7 +379,7 @@ export function useFetch( online: false, loading: false, error: false, - completedAttempts: false + completedAttempts: false, }).current const inDeps = (k: keyof typeof thisDeps) => { @@ -400,20 +400,20 @@ export function useFetch( } function setData(v: any) { - setFetchState(p => { + setFetchState((p) => { if (isFunction(v)) { const newVal = v(p.data) if (!jsonCompare(p.data, newVal)) { return { ...p, - data: newVal + data: newVal, } } } else { if (!jsonCompare(p.data, v)) { return { ...p, - data: v + data: v, } } } @@ -426,11 +426,11 @@ export function useFetch( const rawJSON = serialize(data) function setOnline(v: any) { - setFetchState(p => { + setFetchState((p) => { if (online !== p.online) { return { ...p, - online: v + online: v, } } return p @@ -439,24 +439,24 @@ export function useFetch( const requestHeaders = { ...ctx.headers, - ...config.headers + ...config.headers, } function setError(v: any) { - setFetchState(p => { + setFetchState((p) => { if (isFunction(v)) { const newErroValue = v(p.error) if (newErroValue !== p.error) { return { ...p, - error: newErroValue + error: newErroValue, } } } else { if (v !== p.error) { return { ...p, - error: v + error: v, } } } @@ -465,20 +465,20 @@ export function useFetch( } function setLoading(v: any) { - setFetchState(p => { + setFetchState((p) => { if (isFunction(v)) { const newLoadingValue = v(p.loading) if (newLoadingValue !== p.loading) { return { ...p, - loading: newLoadingValue + loading: newLoadingValue, } } } else { if (v !== p.loading) { return { ...p, - loading: v + loading: v, } } } @@ -487,20 +487,20 @@ export function useFetch( } function setCompletedAttempts(v: any) { - setFetchState(p => { + setFetchState((p) => { if (isFunction(v)) { const newCompletedAttempts = v(p.completedAttempts) if (newCompletedAttempts !== p.completedAttempts) { return { ...p, - completedAttempts: newCompletedAttempts + completedAttempts: newCompletedAttempts, } } } else { if (v !== p.completedAttempts) { return { ...p, - completedAttempts: v + completedAttempts: v, } } } @@ -511,7 +511,7 @@ export function useFetch( const requestAbortController: AbortController = abortControllers.get(resolvedKey) ?? new AbortController() - const isGqlRequest = isDefined((optionsConfig as any)['__gql']) + const isGqlRequest = isDefined((optionsConfig as any)["__gql"]) const fetchData = useCallback( async function fetchData( @@ -519,10 +519,10 @@ export function useFetch( ) { const rawUrl = (hasBaseUrl(url) - ? '' + ? "" : !isDefined(config.baseUrl) ? !isDefined(ctx.baseUrl) - ? '' + ? "" : ctx.baseUrl : config.baseUrl) + url @@ -530,20 +530,20 @@ export function useFetch( const realUrl = urlWithParams + - (urlWithParams.includes('?') ? (c?.query !== '' ? `&` : '') : '') + (urlWithParams.includes("?") ? (c?.query !== "" ? `&` : "") : "") if ( !jsonCompare( - JSON.parse(previousConfig.get(resolvedKey) || '{}'), + JSON.parse(previousConfig.get(resolvedKey) || "{}"), optionsConfig ) ) { previousProps.set(resolvedKey, optionsConfig) queue(() => { - if (url !== '') { + if (url !== "") { const newUrls = { realUrl, - rawUrl + rawUrl, } urls[resolvedKey] = newUrls @@ -567,7 +567,7 @@ export function useFetch( requestCallId: loadingFirst ? requestCallId : undefined, loading: true, requestAbortController: newAbortController, - error: false + error: false, }) abortControllers.set(resolvedKey, newAbortController) @@ -589,7 +589,7 @@ export function useFetch( } } - cacheProvider.set('requestStart' + resolvedDataKey, Date.now()) + cacheProvider.set("requestStart" + resolvedDataKey, Date.now()) requestInitialTimes.set(resolvedDataKey, Date.now()) const newRequestConfig = ( @@ -602,12 +602,12 @@ export function useFetch( return newAbortController.signal })(), headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...ctx.headers, ..._headers, ...config.headers, - ...c.headers - } + ...c.headers, + }, } : { ...ctx, @@ -624,23 +624,23 @@ export function useFetch( headers: { ...(temporaryFormData.get(resolvedKey) ? {} - : { 'Content-Type': 'application/json' }), + : { "Content-Type": "application/json" }), ...ctx.headers, ...config.headers, - ...c.headers - } + ...c.headers, + }, } ) as any const r = new Request( ( realUrl + - (realUrl.includes('?') + (realUrl.includes("?") ? c.query : c.query - ? '?' + c.query + ? "?" + c.query : c.query) - ).replace('?&', '?'), + ).replace("?&", "?"), newRequestConfig ) @@ -654,11 +654,11 @@ export function useFetch( const resolvedDate = Date.now() cacheProvider.set( - 'expiration' + resolvedDataKey, + "expiration" + resolvedDataKey, resolvedDate + maxAge ) - cacheProvider.set('requestEnds' + resolvedDataKey, resolvedDate) + cacheProvider.set("requestEnds" + resolvedDataKey, resolvedDate) requestResponseTimes.set( resolvedDataKey, getTimePassed(resolvedDataKey) @@ -673,14 +673,14 @@ export function useFetch( ...rpc, response: json, error: false, - code + code, } // @ts-ignore - 'data' is priority because 'fetcher' can return it - const incoming = json?.['data'] ?? (await (resolver as any)(json)) + const incoming = json?.["data"] ?? (await (resolver as any)(json)) // @ts-expect-error - const actionError = json?.['error'] + const actionError = json?.["error"] const _data = isFunction(middleware) ? await middleware!(incoming as any, thisCache) @@ -690,7 +690,7 @@ export function useFetch( ? { ..._data, variables: (optionsConfig as any)?.variables, - errors: _data?.errors ? _data.errors : undefined + errors: _data?.errors ? _data.errors : undefined, } : _data @@ -708,7 +708,7 @@ export function useFetch( rpc = { ...rpc, - error: false + error: false, } const dataExpirationTime = Date.now() + maxAge @@ -719,7 +719,7 @@ export function useFetch( hasErrors.set(resolvedKey, true) rpc = { ...rpc, - error: true + error: true, } if (handleError) { if (!resolvedOnErrorCalls.get(resolvedKey)) { @@ -737,7 +737,7 @@ export function useFetch( variables: isGqlRequest ? (optionsConfig as any)?.variables || {} : undefined, - completedAttempts: 0 + completedAttempts: 0, } $$data = __data @@ -746,7 +746,7 @@ export function useFetch( if (!_data?.errors && isGqlRequest) { rpc = { ...rpc, - error: false + error: false, } hasErrors.set(resolvedDataKey, false) @@ -769,7 +769,7 @@ export function useFetch( } else { rpc = { ...rpc, - error: actionError ?? true + error: actionError ?? true, } if (!cacheIfError) { hasData.set(resolvedDataKey, false) @@ -780,11 +780,11 @@ export function useFetch( hasData.set(resolvedDataKey, false) hasData.set(resolvedKey, false) } - setFetchState(previous => { + setFetchState((previous) => { const newData = { ...previous, variables: (optionsConfig as any)?.variables, - errors: _data.errors + errors: _data.errors, } as any $$data = newData @@ -794,7 +794,7 @@ export function useFetch( rpc = { ...rpc, data: newData, - error: actionError ?? true + error: actionError ?? true, } cacheProvider.set(resolvedDataKey, newData) @@ -815,7 +815,7 @@ export function useFetch( rpc = { ...rpc, - data: def + data: def, } } if (handleError) { @@ -849,7 +849,7 @@ export function useFetch( rpc = { ...rpc, - error: err ?? true + error: err ?? true, } if (cacheIfError) { @@ -859,7 +859,7 @@ export function useFetch( rpc = { ...rpc, - data: thisCache + data: thisCache, } } } else { @@ -867,7 +867,7 @@ export function useFetch( rpc = { ...rpc, - data: def + data: def, } cacheForMutation.set(idString, def) @@ -875,7 +875,7 @@ export function useFetch( rpc = { ...rpc, - error: err ?? true + error: err ?? true, } hasErrors.set(resolvedDataKey, err ?? true) @@ -889,7 +889,7 @@ export function useFetch( } else { rpc = { ...rpc, - loading: true + loading: true, } if (!isPending(resolvedKey)) { if (!isDefined(cacheProvider.get(resolvedDataKey))) { @@ -900,7 +900,7 @@ export function useFetch( rpc = { ...rpc, data: def, - loading: true + loading: true, } } } @@ -919,7 +919,7 @@ export function useFetch( hasErrors.get(resolvedDataKey) || false, ...rpc, - loading: false + loading: false, }) willSuspend.set(resolvedKey, false) @@ -944,7 +944,7 @@ export function useFetch( requestCallId, memory, def, - loadingFirst + loadingFirst, ] ) @@ -960,21 +960,21 @@ export function useFetch( } } } - signal?.addEventListener('abort', abortCallback) + signal?.addEventListener("abort", abortCallback) return () => { - signal?.removeEventListener('abort', abortCallback) + signal?.removeEventListener("abort", abortCallback) } }, [requestAbortController, resolvedKey, onAbort, loading]) const imperativeFetch = useMemo(() => { const __headers = { ...ctx.headers, - ...config.headers + ...config.headers, } const __params = { ...ctx.params, - ...config.params + ...config.params, } const __baseUrl = isDefined(config.baseUrl) ? config.baseUrl : ctx.baseUrl @@ -982,7 +982,7 @@ export function useFetch( ...ctx, headers: __headers, baseUrl: __baseUrl, - params: __params + params: __params, }) }, [serialize(ctx)]) @@ -994,7 +994,7 @@ export function useFetch( error: $error, online, loading, - completedAttempts + completedAttempts, } = v || {} if (isMutating) { @@ -1003,7 +1003,7 @@ export function useFetch( if (isMutating) { forceMutate($data) if (handleMutate) { - if (url === '') { + if (url === "") { ;(onMutate as any)($data, imperativeFetch) } else { if (!runningMutate.get(resolvedKey)) { @@ -1019,31 +1019,31 @@ export function useFetch( if (v.requestCallId !== requestCallId) { if (!willSuspend.get(resolvedKey)) { queue(() => { - if (inDeps('data')) { + if (inDeps("data")) { if (isDefined($data)) { if (!jsonCompare(data, cacheProvider.get(resolvedDataKey))) { setData(cacheProvider.get(resolvedKey)) } } } - if (inDeps('online')) { + if (inDeps("online")) { if (isDefined(online)) { setOnline(online) } } - if (inDeps('loading')) { + if (inDeps("loading")) { if (isDefined(loading)) { setLoading(loading) } } - if (inDeps('error')) { + if (inDeps("error")) { if (isDefined($error)) { if (fetchState.error !== $error) { setError($error) } } } - if (inDeps('completedAttempts')) { + if (inDeps("completedAttempts")) { if (isDefined(completedAttempts)) { setCompletedAttempts(completedAttempts) } @@ -1064,7 +1064,7 @@ export function useFetch( resolvedKey, resolvedDataKey, requestCallId, - fetchState + fetchState, ]) const reValidate = useCallback( @@ -1081,18 +1081,18 @@ export function useFetch( if (!isPending(resolvedKey)) { // preventing revalidation where only need updates about // 'loading', 'error' and 'data' because the url can be ommited. - if (url !== '') { + if (url !== "") { fetchData({ query: Object.keys(reqQuery) - .map(q => + .map((q) => Array.isArray(reqQuery[q]) ? reqQuery[q] - .map((queryItem: any) => [q, queryItem].join('=')) - .join('&') - : [q, reqQuery[q]].join('=') + .map((queryItem: any) => [q, queryItem].join("=")) + .join("&") + : [q, reqQuery[q]].join("=") ) - .join('&'), - params: reqParams + .join("&"), + params: reqParams, }) } } @@ -1113,7 +1113,7 @@ export function useFetch( ctx.auto, idString, fetchState, - id + id, ]) useEffect(() => { @@ -1124,7 +1124,7 @@ export function useFetch( } requestsProvider.emit(resolvedKey, { requestCallId, - online: true + online: true, }) setOnline(true) offlineHandled.set(resolvedKey, false) @@ -1141,9 +1141,9 @@ export function useFetch( function addOnlineListener() { if (windowExists) { - if ('addEventListener' in window) { + if ("addEventListener" in window) { if (retryOnReconnect) { - window.addEventListener('online', backOnline) + window.addEventListener("online", backOnline) } } } @@ -1153,8 +1153,8 @@ export function useFetch( return () => { if (windowExists) { - if ('addEventListener' in window) { - window.removeEventListener('online', backOnline) + if ("addEventListener" in window) { + window.removeEventListener("online", backOnline) } } } @@ -1166,7 +1166,7 @@ export function useFetch( setOnline(false) requestsProvider.emit(resolvedKey, { requestCallId, - online: false + online: false, }) onlineHandled.set(resolvedKey, false) if (handleOffline) { @@ -1179,8 +1179,8 @@ export function useFetch( function addOfflineListener() { if (windowExists) { - if ('addEventListener' in window) { - window.addEventListener('offline', wentOffline) + if ("addEventListener" in window) { + window.addEventListener("offline", wentOffline) } } } @@ -1189,8 +1189,8 @@ export function useFetch( return () => { if (windowExists) { - if ('addEventListener' in window) { - window.removeEventListener('offline', wentOffline) + if ("addEventListener" in window) { + window.removeEventListener("offline", wentOffline) } } } @@ -1200,7 +1200,7 @@ export function useFetch( return () => { if (revalidateOnMount) { if (canRevalidate) { - if (url !== '') { + if (url !== "") { if (suspenseInitialized.get(resolvedKey)) { queue(() => { previousConfig.set(resolvedKey, undefined) @@ -1233,7 +1233,7 @@ export function useFetch( if (!gettingAttempts.get(resolvedKey)) { gettingAttempts.set(resolvedKey, true) const attempts = - typeof $attempts === 'function' + typeof $attempts === "function" ? $attempts({ status: statusCodes.get(resolvedKey) || @@ -1243,7 +1243,7 @@ export function useFetch( hasErrors.get(resolvedKey) || hasErrors.get(resolvedDataKey) || (error as any), - completedAttempts + completedAttempts, }) : $attempts @@ -1255,7 +1255,7 @@ export function useFetch( requestsProvider.emit(resolvedKey, { requestCallId, - completedAttempts: newAttemptsValue + completedAttempts: newAttemptsValue, }) return newAttemptsValue @@ -1264,9 +1264,9 @@ export function useFetch( requestsProvider.emit(resolvedKey, { requestCallId, online: false, - error: true + error: true, }) - if (inDeps('online')) setOnline(false) + if (inDeps("online")) setOnline(false) } } } @@ -1284,7 +1284,7 @@ export function useFetch( fetchState, attemptInterval, resolvedKey, - completedAttempts + completedAttempts, ]) useEffect(() => { @@ -1307,7 +1307,7 @@ export function useFetch( rawJSON, canRevalidate, completedAttempts, - config + config, ]) const initializeRevalidation = useCallback( @@ -1315,28 +1315,28 @@ export function useFetch( ? async function initializeRevalidation() { let d = undefined if (canRevalidate) { - if (url !== '') { + if (url !== "") { d = await fetchData({ query: Object.keys(reqQuery) - .map(q => + .map((q) => Array.isArray(reqQuery[q]) ? reqQuery[q] - .map((queryItem: any) => [q, queryItem].join('=')) - .join('&') - : [q, reqQuery[q]].join('=') + .map((queryItem: any) => [q, queryItem].join("=")) + .join("&") + : [q, reqQuery[q]].join("=") ) - .join('&'), - params: reqParams + .join("&"), + params: reqParams, }) } else { d = def // It means a url is not passed - setFetchState(prev => ({ + setFetchState((prev) => ({ ...prev, loading: false, error: hasErrors.get(resolvedDataKey) || hasErrors.get(resolvedKey), - completedAttempts: prev.completedAttempts + completedAttempts: prev.completedAttempts, })) } } else { @@ -1353,17 +1353,17 @@ export function useFetch( ) if (!suspense) { - if (url !== '') { + if (url !== "") { suspenseInitialized.set(resolvedKey, true) } } useIsomorphicLayoutEffect(() => { const fn = () => { - if (url !== '') { + if (url !== "") { if (!jsonCompare(previousProps.get(resolvedKey), optionsConfig)) { abortControllers.get(resolvedKey)?.abort() - if (inDeps('data')) { + if (inDeps("data")) { queue(initializeRevalidation) } } @@ -1412,15 +1412,15 @@ Learn more: https://httpr.vercel.app/docs/api#suspense const fn = () => { if (!runningRequests.get(resolvedKey) && canRevalidate) { if (windowExists) { - if (canRevalidate && url !== '') { + if (canRevalidate && url !== "") { if ( !jsonCompare( - JSON.parse(previousConfig.get(resolvedKey) || '{}'), + JSON.parse(previousConfig.get(resolvedKey) || "{}"), optionsConfig ) ) { if (!isPending(resolvedKey)) { - if (inDeps('data')) { + if (inDeps("data")) { initializeRevalidation() } } else { @@ -1445,13 +1445,13 @@ Learn more: https://httpr.vercel.app/docs/api#suspense const revalidateAfterUnmount = revalidateOnMount ? true : !jsonCompare( - JSON.parse(previousConfig.get(resolvedKey) || '{}'), + JSON.parse(previousConfig.get(resolvedKey) || "{}"), optionsConfig ) function revalidate() { if (!debounce && !canDebounce.get(resolvedKey)) { - if (inDeps('data')) { + if (inDeps("data")) { initializeRevalidation() } } @@ -1483,8 +1483,8 @@ Learn more: https://httpr.vercel.app/docs/api#suspense useEffect(() => { function addFocusListener() { if (revalidateOnFocus && windowExists) { - if ('addEventListener' in window) { - window.addEventListener('focus', reValidate as any) + if ("addEventListener" in window) { + window.addEventListener("focus", reValidate as any) } } } @@ -1493,8 +1493,8 @@ Learn more: https://httpr.vercel.app/docs/api#suspense return () => { if (windowExists) { - if ('addEventListener' in window) { - window.removeEventListener('focus', reValidate as any) + if ("addEventListener" in window) { + window.removeEventListener("focus", reValidate as any) } } } @@ -1506,7 +1506,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense loading, reValidate, refresh, - serialize(config) + serialize(config), ]) const __config = { @@ -1515,20 +1515,20 @@ Learn more: https://httpr.vercel.app/docs/api#suspense ...previousProps.get(resolvedKey), params: { ...reqParams, - ...previousProps.get(resolvedKey)?.params + ...previousProps.get(resolvedKey)?.params, }, headers: { ...requestHeaders, - ...previousProps.get(resolvedKey)?.headers + ...previousProps.get(resolvedKey)?.headers, }, body: config.body, baseUrl: ctx.baseUrl || config.baseUrl, - url: configUrl?.realUrl?.replace('?', ''), + url: configUrl?.realUrl?.replace("?", ""), rawUrl: configUrl?.rawUrl, query: { ...reqQuery, - ...previousProps.get(resolvedKey)?.query - } + ...previousProps.get(resolvedKey)?.query, + }, } function forceMutate( @@ -1548,7 +1548,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense requestsProvider.emit(resolvedKey, { requestCallId, isMutating: true, - data: newValue + data: newValue, }) setData(newValue as any) } @@ -1564,7 +1564,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense requestsProvider.emit(resolvedKey, { requestCallId, isMutating: true, - data: newVal + data: newVal, }) setData(newVal) @@ -1573,12 +1573,12 @@ Learn more: https://httpr.vercel.app/docs/api#suspense } const [$requestStart, $requestEnd] = [ - notNull(cacheProvider.get('requestStart' + resolvedDataKey)) - ? new Date(cacheProvider.get('requestStart' + resolvedDataKey)) + notNull(cacheProvider.get("requestStart" + resolvedDataKey)) + ? new Date(cacheProvider.get("requestStart" + resolvedDataKey)) + : null, + notNull(cacheProvider.get("requestEnds" + resolvedDataKey)) + ? new Date(cacheProvider.get("requestEnds" + resolvedDataKey)) : null, - notNull(cacheProvider.get('requestEnds' + resolvedDataKey)) - ? new Date(cacheProvider.get('requestEnds' + resolvedDataKey)) - : null ] const expirationDate = error @@ -1587,8 +1587,8 @@ Learn more: https://httpr.vercel.app/docs/api#suspense : null : maxAge === 0 ? null - : notNull(cacheProvider.get('expiration' + resolvedDataKey)) - ? new Date(cacheProvider.get('expiration' + resolvedDataKey)) + : notNull(cacheProvider.get("expiration" + resolvedDataKey)) + ? new Date(cacheProvider.get("expiration" + resolvedDataKey)) : null const isFailed = @@ -1610,7 +1610,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense if (isFormData(form)) { if (formRef.current) { if (onSubmit) { - if (onSubmit !== 'reset') { + if (onSubmit !== "reset") { onSubmit(formRef.current, form) } else { if (formRef.current) { @@ -1634,7 +1634,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense hasErrors.set(resolvedDataKey, false) requestsProvider.emit(resolvedKey, { - error: false + error: false, }) } @@ -1649,7 +1649,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense }, formProps: { action: submit, - ref: formRef + ref: formRef, }, formRef, get revalidating() { @@ -1746,7 +1746,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense requestCallId, error: false, loading: false, - data: requestCache + data: requestCache, }) } } @@ -1760,7 +1760,7 @@ Learn more: https://httpr.vercel.app/docs/api#suspense /** * The request key */ - key: resolvedKey + key: resolvedKey, } as unknown as { refresh(): void resetError(): void @@ -1808,15 +1808,15 @@ Learn more: https://httpr.vercel.app/docs/api#suspense } } -useFetch.get = createRequestFn('GET', '', {}) -useFetch.delete = createRequestFn('DELETE', '', {}) -useFetch.head = createRequestFn('HEAD', '', {}) -useFetch.options = createRequestFn('OPTIONS', '', {}) -useFetch.post = createRequestFn('POST', '', {}) -useFetch.put = createRequestFn('PUT', '', {}) -useFetch.patch = createRequestFn('PATCH', '', {}) -useFetch.purge = createRequestFn('PURGE', '', {}) -useFetch.link = createRequestFn('LINK', '', {}) -useFetch.unlink = createRequestFn('UNLINK', '', {}) +useFetch.get = createRequestFn("GET", "", {}) +useFetch.delete = createRequestFn("DELETE", "", {}) +useFetch.head = createRequestFn("HEAD", "", {}) +useFetch.options = createRequestFn("OPTIONS", "", {}) +useFetch.post = createRequestFn("POST", "", {}) +useFetch.put = createRequestFn("PUT", "", {}) +useFetch.patch = createRequestFn("PATCH", "", {}) +useFetch.purge = createRequestFn("PURGE", "", {}) +useFetch.link = createRequestFn("LINK", "", {}) +useFetch.unlink = createRequestFn("UNLINK", "", {}) useFetch.extend = createImperativeFetch