reactjs - SWR Vercel global konfiguration med Typescript
Jag vill skapa ett objekt med SWR-konfigurationer för att ställa in dem globalt. Jag använder ConfigInterface-typen som kommer från SWR.
import { ConfigInterface } from 'swr';
import fetcher from 'api/axiosFetcher';
const swrConfig: ConfigInterface = {
fetcher,
};
export default swrConfig;
Problemet är när jag försöker använda detta objekt inuti SWRConfig
<SWRConfig value={swrConfig}>
visar nästa fel
Type 'ConfigInterface<any, any, fetcherFn<any>>' is not assignable to type 'ConfigInterface<any, any, (...args: any) => any>'.
Types of property 'fetcher' are incompatible.
Type '((...args: any) => any) | null | undefined' is not assignable to type '((...args: any) => any) | undefined'.
Type 'null' is not assignable to type '((...args: any) => any) | undefined'.ts(2322)
Min hämtarfunktion
const fetcher = <T>(url: string): Promise<T> =>
axiosInstance
.get(url)
.then((response) => {
if (response.statusText === 'OK') {
return response.data;
}
throw new Error(response.statusText);
})
.catch(({ response }) => {
throw new Error(response.statusText);
});
Svar #1
Skriver upp några egna TypeDefs för din fråga.
- Först, skriv din funktion som en TypeScript Class, en som accepterar ett generiskt argument (T). På detta sätt kan du tillämpa en begränsning (T) på en klass som Mixin appliceras på
type FetcherConstructor<T = {}> = new (...args: any[]) => T;
- Vår klass fungerar bara om url-parametern får ett strängvärde -- den obligatoriska url-parametern är ett exempel på att implementera en tillämpad begränsning (nämnd ovan)
type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
Som du kan se är det villkorliga RequestInit-gränssnittet ganska omfattande
interface RequestInit {
/**
* A BodyInit object or null to set request's body.
*/
body?: BodyInit | null;
/**
* A string indicating how the request will interact with the browser's cache to set request's cache.
*/
cache?: RequestCache;
/**
* A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials.
*/
credentials?: RequestCredentials;
/**
* A Headers object, an object literal, or an array of two-item arrays to set request's headers.
*/
headers?: HeadersInit;
/**
* A cryptographic hash of the resource to be fetched by request. Sets request's integrity.
*/
integrity?: string;
/**
* A boolean to set request's keepalive.
*/
keepalive?: boolean;
/**
* A string to set request's method.
*/
method?: string;
/**
* A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode.
*/
mode?: RequestMode;
/**
* A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect.
*/
redirect?: RequestRedirect;
/**
* A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer.
*/
referrer?: string;
/**
* A referrer policy to set request's referrerPolicy.
*/
referrerPolicy?: ReferrerPolicy;
/**
* An AbortSignal to set request's signal.
*/
signal?: AbortSignal | null;
/**
* Can only be null. Used to disassociate request from any Window.
*/
window?: any;
}
- Där bodyInit-typen definieras enligt följande
type BodyInit = Blob | BufferSource | FormData | URLSearchParams | ReadableStream<Uint8Array> | string;
- Och
Response-gränssnittet, som ärtypeof fetcheri detta exempel, har följande svargränssnitt som sin returnerade payload
/** This Fetch API interface represents the response to a request. */
interface Response extends Body {
readonly headers: Headers;
readonly ok: boolean;
readonly redirected: boolean;
readonly status: number;
readonly statusText: string;
readonly trailer: Promise<Headers>;
readonly type: ResponseType;
readonly url: string;
clone(): Response;
}
Kolla in mixins här för mer förklaring.
- En enkel praktisk implementering
export default async function FetcherExample(
fetch: FetcherAbstracted
) {
const exactPath = 'docs/handbook/mixins.html';
const data: Response = await new fetch().fetcher(
`https://typescriptlang.org${exactPath}`,
{
body: exactPath,
method: 'GET',
headers: {
'Content-Type': 'application/json'
// ...
},
credentials: "include"
}
);
return await data.json();
}
Samlar nu allt på ett ställe i ett kodexempel för tydlighet
export type FetcherConstructor<T = {}> = new (...args: any[]) => T;
export type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
export default async function FetcherExample(
fetch: FetcherAbstracted
) {
const exactPath = 'docs/handbook/mixins.html';
const data: Response = await new fetch().fetcher(
`https://typescriptlang.org${exactPath}`,
{
body: exactPath,
method: 'GET',
headers: {
'Content-Type': 'application/json'
// ...
},
credentials: "include"
}
);
return await data.json();
}
UPPDATERA
För att besvara din fråga kortfattat bör denna hook fungera med axios+SWR, vilket är liknande den parameterbegränsade generiska jag skrev ut ovan
type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
Så pass mycket att du skulle kunna använda det för din Axios fetcher-implementation.
const fetcher: FetcherAbstracted = async (url: string) => {
try {
const res = await Axios.get(url);
return res.data;
} catch (error) {
throw error.response.data;
}
};
