diff --git a/docs/rtk-query/api/fetchBaseQuery.mdx b/docs/rtk-query/api/fetchBaseQuery.mdx index 79420f7032..29107aee87 100644 --- a/docs/rtk-query/api/fetchBaseQuery.mdx +++ b/docs/rtk-query/api/fetchBaseQuery.mdx @@ -64,7 +64,7 @@ type FetchBaseQueryArgs = { api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - >, + > & { args: string | FetchArgs }, ) => MaybePromise fetchFn?: ( input: RequestInfo, @@ -105,7 +105,7 @@ Typically a string like `https://api.your-really-great-app.com/v1/`. If you don' _(optional)_ -Allows you to inject headers on every request. You can specify headers at the endpoint level, but you'll typically want to set common headers like `authorization` here. As a convenience mechanism, the second argument allows you to use `getState` to access your redux store in the event you store information you'll need there such as an auth token. Additionally, it provides access to `extra`, `endpoint`, `type`, and `forced` to unlock more granular conditional behaviors. +Allows you to inject headers on every request. You can specify headers at the endpoint level, but you'll typically want to set common headers like `authorization` here. As a convenience mechanism, the second argument allows you to use `getState` to access your redux store in the event you store information you'll need there such as an auth token. Additionally, it provides access to `args`, `extra`, `endpoint`, `type`, and `forced` to unlock more granular conditional behaviors. You can mutate the `headers` argument directly, and returning it is optional. @@ -114,6 +114,7 @@ type prepareHeaders = ( headers: Headers, api: { getState: () => unknown + args: string | FetchArgs extra: unknown endpoint: string type: 'query' | 'mutation' @@ -303,8 +304,8 @@ The default response handler is `"json"`, which is equivalent to the following f ```ts title="Default responseHandler" const defaultResponseHandler = async (res: Response) => { - const text = await res.text(); - return text.length ? JSON.parse(text) : null; + const text = await res.text() + return text.length ? JSON.parse(text) : null } ``` diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index 9dc14d9790..9a78c17695 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -112,7 +112,7 @@ export type FetchBaseQueryArgs = { api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - >, + > & { args: string | FetchArgs }, ) => MaybePromise fetchFn?: ( input: RequestInfo, @@ -164,9 +164,9 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * The base URL for an API service. * Typically in the format of https://example.com/ * - * @param {(headers: Headers, api: { getState: () => unknown; extra: unknown; endpoint: string; type: 'query' | 'mutation'; forced: boolean; }) => Headers} prepareHeaders + * @param {(headers: Headers, api: { getState: () => unknown; args: string | FetchArgs; extra: unknown; endpoint: string; type: 'query' | 'mutation'; forced: boolean; }) => Headers} prepareHeaders * An optional function that can be used to inject headers on requests. - * Provides a Headers object, as well as most of the `BaseQueryApi` (`dispatch` is not available). + * Provides a Headers object, most of the `BaseQueryApi` (`dispatch` is not available), and the args passed into the query function. * Useful for setting authentication or headers that need to be set conditionally. * * @link https://developer.mozilla.org/en-US/docs/Web/API/Headers @@ -212,7 +212,7 @@ export function fetchBaseQuery({ 'Warning: `fetch` is not available. Please supply a custom `fetchFn` property to use `fetchBaseQuery` on SSR environments.', ) } - return async (arg, api) => { + return async (args, api) => { const { getState, extra, endpoint, forced, type } = api let meta: FetchBaseQueryMeta | undefined let { @@ -223,9 +223,10 @@ export function fetchBaseQuery({ validateStatus = globalValidateStatus ?? defaultValidateStatus, timeout = defaultTimeout, ...rest - } = typeof arg == 'string' ? { url: arg } : arg + } = typeof args == 'string' ? { url: args } : args - let abortController: AbortController | undefined, signal = api.signal + let abortController: AbortController | undefined, + signal = api.signal if (timeout) { abortController = new AbortController() api.signal.addEventListener('abort', abortController.abort) @@ -242,6 +243,7 @@ export function fetchBaseQuery({ config.headers = (await prepareHeaders(headers, { getState, + args, extra, endpoint, forced, @@ -297,7 +299,10 @@ export function fetchBaseQuery({ } } finally { if (timeoutId) clearTimeout(timeoutId) - abortController?.signal.removeEventListener('abort', abortController.abort) + abortController?.signal.removeEventListener( + 'abort', + abortController.abort, + ) } const responseClone = response.clone() diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index 6160eade9e..2cf0b17109 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -799,16 +799,17 @@ describe('fetchBaseQuery', () => { }) test('prepareHeaders provides extra api information for getState, extra, endpoint, type and forced', async () => { - let _getState, _extra, _endpoint, _type, _forced + let _getState, _args: any, _extra, _endpoint, _type, _forced const baseQuery = fetchBaseQuery({ baseUrl, fetchFn: fetchFn as any, prepareHeaders: ( headers, - { getState, extra, endpoint, type, forced }, + { getState, args, extra, endpoint, type, forced }, ) => { _getState = getState + _args = args _endpoint = endpoint _type = type _forced = forced @@ -845,6 +846,7 @@ describe('fetchBaseQuery', () => { await doRequest() expect(_getState).toBeDefined() + expect(_args!.url).toBe('/echo') expect(_endpoint).toBe('someEndpointName') expect(_type).toBe('query') expect(_forced).toBe(true)