A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://redux-toolkit.js.org/rtk-query/api/fetchBaseQuery below:

fetchBaseQuery | Redux Toolkit

fetchBaseQuery

This is a very small wrapper around fetch that aims to simplify HTTP requests. It is not a full-blown replacement for axios, superagent, or any other more heavyweight library, but it will cover the vast majority of your HTTP request needs.

fetchBaseQuery is a factory function that generates a data fetching method compatible with RTK Query's baseQuery configuration option. It takes all standard options from fetch's RequestInit interface, as well as baseUrl, a prepareHeaders function, an optional fetch function, a paramsSerializer function, and a timeout.

Basic Usage

To use it, import it when you are creating an API service definition, call it as fetchBaseQuery(options), and pass the result as the baseQuery field in createApi:

src/services/pokemon.ts


import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const pokemonApi = createApi({

baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (build) => ({
getPokemonByName: build.query({

query: (name: string) => `pokemon/${name}`,
}),
updatePokemon: build.mutation({
query: ({ name, patch }) => ({
url: `pokemon/${name}`,


method: 'PATCH',


body: patch,
}),
}),
}),
})

src/services/pokemon.js


import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const pokemonApi = createApi({

baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (build) => ({
getPokemonByName: build.query({

query: (name) => `pokemon/${name}`,
}),
updatePokemon: build.mutation({
query: ({ name, patch }) => ({
url: `pokemon/${name}`,


method: 'PATCH',


body: patch,
}),
}),
}),
})
Signature

fetchBaseQuery signature

type FetchBaseQuery = (
args: FetchBaseQueryArgs,
) => (
args: string | FetchArgs,
api: BaseQueryApi,
extraOptions: ExtraOptions,
) => FetchBaseQueryResult

type FetchBaseQueryArgs = {
baseUrl?: string
prepareHeaders?: (
headers: Headers,
api: Pick<
BaseQueryApi,
'getState' | 'extra' | 'endpoint' | 'type' | 'forced'
> & { arg: string | FetchArgs },
) => MaybePromise<Headers | void>
fetchFn?: (
input: RequestInfo,
init?: RequestInit | undefined,
) => Promise<Response>
paramsSerializer?: (params: Record<string, any>) => string
isJsonContentType?: (headers: Headers) => boolean
jsonContentType?: string
timeout?: number
} & RequestInit

type FetchBaseQueryResult = Promise<
| {
data: any
error?: undefined
meta?: { request: Request; response: Response }
}
| {
error: FetchBaseQueryError
data?: undefined
meta?: { request: Request; response: Response }
}
>

type FetchBaseQueryError =
| {




status: number
data: unknown
}
| {




status: 'FETCH_ERROR'
data?: undefined
error: string
}
| {






status: 'PARSING_ERROR'
originalStatus: number
data: string
error: string
}
| {




status: 'TIMEOUT_ERROR'
data?: undefined
error: string
}
| {




status: 'CUSTOM_ERROR'
data?: unknown
error: string
}
Parameters baseUrl

(required)

Typically a string like https://api.your-really-great-app.com/v1/. If you don't provide a baseUrl, it defaults to a relative path from where the request is being made. You should most likely always specify this.

(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 arg, extra, endpoint, type, and forced to unlock more granular conditional behaviors.

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

prepareHeaders signature

type prepareHeaders = (
headers: Headers,
api: {
getState: () => unknown
arg: string | FetchArgs
extra: unknown
endpoint: string
type: 'query' | 'mutation'
forced: boolean | undefined
},
) => Headers | void
paramsSerializer

(optional)

A function that can be used to apply custom transformations to the data passed into params. If you don't provide this, params will be given directly to new URLSearchParams(). With some API integrations, you may need to leverage this to use something like the query-string library to support different array types.

fetchFn

(optional)

A fetch function that overrides the default on the window. Can be useful in SSR environments where you may need to leverage isomorphic-fetch or cross-fetch.

timeout

(optional)

A number in milliseconds that represents the maximum time a request can take before timing out.

isJsonContentType

(optional)

A callback that receives a Headers object and determines the body field of the FetchArgs argument should be stringified via JSON.stringify().

The default implementation inspects the content-type header, and will match values like "application/json" and "application/vnd.api+json".

jsonContentType

(optional)

Used when automatically setting the content-type header for a request with a jsonifiable body that does not have an explicit content-type header. Defaults to "application/json".

Common Usage Patterns

The most common use case for prepareHeaders would be to automatically include authorization headers for your API requests.

import { fetchBaseQuery } from '@reduxjs/toolkit/query'
import type { RootState } from './store'

const baseQuery = fetchBaseQuery({
baseUrl: '/',
prepareHeaders: (headers, { getState }) => {
const token = (getState() as RootState).auth.token


if (token) {
headers.set('authorization', `Bearer ${token}`)
}

return headers
},
})
import { fetchBaseQuery } from '@reduxjs/toolkit/query'

const baseQuery = fetchBaseQuery({
baseUrl: '/',
prepareHeaders: (headers, { getState }) => {
const token = getState().auth.token


if (token) {
headers.set('authorization', `Bearer ${token}`)
}

return headers
},
})
Individual query options

There is more behavior that you can define on a per-request basis. The query field may return an object containing any of the default fetch options available to the RequestInit interface, as well as these additional options:

endpoint request options

interface FetchArgs extends RequestInit {
url: string
params?: Record<string, any>
body?: any
responseHandler?:
| 'json'
| 'text'
| `content-type`
| ((response: Response) => Promise<any>)
validateStatus?: (response: Response, body: any) => boolean
timeout?: number
}

const defaultValidateStatus = (response: Response) =>
response.status >= 200 && response.status <= 299

endpoint request options

const defaultValidateStatus = (response) =>
response.status >= 200 && response.status <= 299
Setting the body

By default, fetchBaseQuery assumes that every request you make will be json, so in those cases all you have to do is set the url and pass a body object when appropriate. For other implementations, you can manually set the Headers to specify the content type.

json
 
endpoints: (build) => ({
updateUser: build.query({
query: (user: Record<string, string>) => ({
url: `users`,
method: 'PUT',
body: user
}),
}),
text
 
endpoints: (build) => ({
updateUser: build.query({
query: (user: Record<string, string>) => ({
url: `users`,
method: 'PUT',
headers: {
'content-type': 'text/plain',
},
body: user
}),
}),
Setting the query string

fetchBaseQuery provides a simple mechanism that converts an object to a serialized query string by passing the object to new URLSearchParms(). If this doesn't suit your needs, you have two options:

  1. Pass the paramsSerializer option to fetchBaseQuery to apply custom transformations
  2. Build your own querystring and set it in the url
 
endpoints: (build) => ({
updateUser: build.query({
query: (user: Record<string, string>) => ({
url: `users`,


params: user
}),
}),
Parsing a Response

By default, fetchBaseQuery assumes that every Response you get will be parsed as json. In the event that you don't want that to happen, you can customize the behavior by specifying an alternative response handler like text, or take complete control and use a custom function that accepts the raw Response object — allowing you to use any Response method.

The responseHandler field can be either:

type ResponseHandler =
| 'content-type'
| 'json'
| 'text'
| ((response: Response) => Promise<any>)

The "json" and "text" values instruct fetchBaseQuery to the corresponding fetch response methods for reading the body. content-type will check the header field to first determine if this appears to be JSON, and then use one of those two methods. The callback allows you to process the body yourself.

Parse a Response as text

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const customApi = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,

responseHandler: (response) => response.text(),
}),
}),
}),
})

Parse a Response as text

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const customApi = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,

responseHandler: (response) => response.text(),
}),
}),
}),
})

Note about responses that return an undefined body

If you make a json request to an API that only returns a 200 with an undefined body, fetchBaseQuery will pass that through as undefined and will not try to parse it as json. This can be common with some APIs, especially on delete requests.

Default response handler

The default response handler is "json", which is equivalent to the following function:

Default responseHandler

const defaultResponseHandler = async (res: Response) => {
const text = await res.text()
return text.length ? JSON.parse(text) : null
}

Default responseHandler

const defaultResponseHandler = async (res) => {
const text = await res.text()
return text.length ? JSON.parse(text) : null
}
Handling non-standard Response status codes

By default, fetchBaseQuery will reject any Response that does not have a status code of 2xx and set it to error. This is the same behavior you've most likely experienced with axios and other popular libraries. In the event that you have a non-standard API you're dealing with, you can use the validateStatus option to customize this behavior.

Using a custom validateStatus

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const customApi = createApi({

baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,


validateStatus: (response, result) =>
response.status === 200 && !result.isError,
}),
}),
}),
})

Using a custom validateStatus

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const customApi = createApi({

baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,


validateStatus: (response, result) =>
response.status === 200 && !result.isError,
}),
}),
}),
})
Adding a custom timeout to requests

By default, fetchBaseQuery has no default timeout value set, meaning your requests will stay pending until your api resolves the request(s) or it reaches the browser's default timeout (normally 5 minutes). Most of the time, this isn't what you'll want. When using fetchBaseQuery, you have the ability to set a timeout on the baseQuery or on individual endpoints. When specifying both options, the endpoint value will take priority.

Setting a timeout value

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const api = createApi({

baseQuery: fetchBaseQuery({ baseUrl: '/api/', timeout: 10000 }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,


timeout: 1000,
}),
}),
}),
})

Setting a timeout value

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

export const api = createApi({

baseQuery: fetchBaseQuery({ baseUrl: '/api/', timeout: 10000 }),
endpoints: (build) => ({
getUsers: build.query({
query: () => ({
url: `users`,


timeout: 1000,
}),
}),
}),
})

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4