Skip to content

Commit

Permalink
Merge pull request #4638 from kyletsang/prepareheaders-args
Browse files Browse the repository at this point in the history
Pass query args to prepareHeaders function
  • Loading branch information
markerikson authored Oct 14, 2024
2 parents c855b8b + 3a22c67 commit d38ff98
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
9 changes: 5 additions & 4 deletions docs/rtk-query/api/fetchBaseQuery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type FetchBaseQueryArgs = {
api: Pick<
BaseQueryApi,
'getState' | 'extra' | 'endpoint' | 'type' | 'forced'
>,
> & { arg: string | FetchArgs },
) => MaybePromise<Headers | void>
fetchFn?: (
input: RequestInfo,
Expand Down Expand Up @@ -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 `arg`, `extra`, `endpoint`, `type`, and `forced` to unlock more granular conditional behaviors.

You can mutate the `headers` argument directly, and returning it is optional.

Expand All @@ -114,6 +114,7 @@ type prepareHeaders = (
headers: Headers,
api: {
getState: () => unknown
arg: string | FetchArgs
extra: unknown
endpoint: string
type: 'query' | 'mutation'
Expand Down Expand Up @@ -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
}
```

Expand Down
15 changes: 10 additions & 5 deletions packages/toolkit/src/query/fetchBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export type FetchBaseQueryArgs = {
api: Pick<
BaseQueryApi,
'getState' | 'extra' | 'endpoint' | 'type' | 'forced'
>,
> & { arg: string | FetchArgs },
) => MaybePromise<Headers | void>
fetchFn?: (
input: RequestInfo,
Expand Down Expand Up @@ -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; arg: 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 arg 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
Expand Down Expand Up @@ -225,7 +225,8 @@ export function fetchBaseQuery({
...rest
} = typeof arg == 'string' ? { url: arg } : arg

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)
Expand All @@ -242,6 +243,7 @@ export function fetchBaseQuery({
config.headers =
(await prepareHeaders(headers, {
getState,
arg,
extra,
endpoint,
forced,
Expand Down Expand Up @@ -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()

Expand Down
6 changes: 4 additions & 2 deletions packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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, _arg: any, _extra, _endpoint, _type, _forced

const baseQuery = fetchBaseQuery({
baseUrl,
fetchFn: fetchFn as any,
prepareHeaders: (
headers,
{ getState, extra, endpoint, type, forced },
{ getState, arg, extra, endpoint, type, forced },
) => {
_getState = getState
_arg = arg
_endpoint = endpoint
_type = type
_forced = forced
Expand Down Expand Up @@ -845,6 +846,7 @@ describe('fetchBaseQuery', () => {
await doRequest()

expect(_getState).toBeDefined()
expect(_arg!.url).toBe('/echo')
expect(_endpoint).toBe('someEndpointName')
expect(_type).toBe('query')
expect(_forced).toBe(true)
Expand Down

0 comments on commit d38ff98

Please sign in to comment.