createApi
createApi
是 RTK Query 功能的核心。它允許您定義一組「端點」,用來描述如何從後端 API 和其他非同步來源擷取資料,包括如何擷取和轉換資料的設定。它會產生一個「API 區段結構」,其中包含 Redux 邏輯(以及 React hooks,視情況而定),可為您封裝資料擷取和快取處理程序。
- TypeScript
- JavaScript
// Need to use the React-specific entry point to allow generating React hooks
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
// Export hooks for usage in function components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
// Need to use the React-specific entry point to allow generating React hooks
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query({
query: (name) => `pokemon/${name}`,
}),
}),
})
// Export hooks for usage in function components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
參數
createApi
接受一個單一設定物件參數,其中包含下列選項
baseQuery(args: InternalQueryArgs, api: BaseQueryApi, extraOptions?: DefinitionExtraOptions): any;
endpoints(build: EndpointBuilder<InternalQueryArgs, TagTypes>): Definitions;
extractRehydrationInfo?: (
action: UnknownAction,
{
reducerPath,
}: {
reducerPath: ReducerPath
}
) =>
| undefined
| CombinedState<Definitions, TagTypes, ReducerPath>
tagTypes?: readonly TagTypes[];
reducerPath?: ReducerPath;
serializeQueryArgs?: SerializeQueryArgs<InternalQueryArgs>;
keepUnusedDataFor?: number; // value is in seconds
refetchOnMountOrArgChange?: boolean | number; // value is in seconds
refetchOnFocus?: boolean;
refetchOnReconnect?: boolean;
baseQuery
每個端點使用的基礎查詢,如果未指定 queryFn
選項。RTK Query 匯出一個名為 fetchBaseQuery 的工具,作為 fetch
的輕量級包裝器,適用於常見的用例。如果你有 fetchBaseQuery
無法處理的需求,請參閱 自訂查詢。
baseQuery 函式引數
args
- 給定端點的query
函式的傳回值api
-BaseQueryApi
物件包含signal
-AbortSignal
物件,可用於中止 DOM 要求和/或讀取要求是否已中止。abort
- 附加到signal
的 AbortController 的abort()
方法。dispatch
- 對應 Redux 儲存體的store.dispatch
方法getState
- 可呼叫來存取目前儲存狀態的函式extra
- 提供給 configureStore getDefaultMiddleware 選項作為 thunk.extraArgument。endpoint
- 端點名稱。type
- 要求類型(query
或mutation
)。forced
- 指出查詢是否已強制執行。
extraOptions
- 為特定端點提供的選用extraOptions
屬性的值
baseQuery 函式簽章
export type BaseQueryFn<
Args = any,
Result = unknown,
Error = unknown,
DefinitionExtraOptions = {},
Meta = {},
> = (
args: Args,
api: BaseQueryApi,
extraOptions: DefinitionExtraOptions,
) => MaybePromise<QueryReturnValue<Result, Error, Meta>>
export interface BaseQueryApi {
signal: AbortSignal
abort: (reason?: string) => void
dispatch: ThunkDispatch<any, any, any>
getState: () => unknown
extra: unknown
endpoint: string
type: 'query' | 'mutation'
forced?: boolean
}
export type QueryReturnValue<T = unknown, E = unknown, M = unknown> =
| {
error: E
data?: undefined
meta?: M
}
| {
error?: undefined
data: T
meta?: M
}
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
// ...endpoints
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
// ...endpoints
}),
})
endpoints
端點只是您想對伺服器執行的操作集合。您可以使用建構器語法將它們定義為物件。有兩種基本端點類型:query
和 mutation
。
有關個別屬性的詳細資訊,請參閱 端點解剖。
查詢端點定義
export type QueryDefinition<
QueryArg,
BaseQuery extends BaseQueryFn,
TagTypes extends string,
ResultType,
ReducerPath extends string = string,
> = {
query(arg: QueryArg): BaseQueryArg<BaseQuery>
/* either `query` or `queryFn` can be present, but not both simultaneously */
queryFn(
arg: QueryArg,
api: BaseQueryApi,
extraOptions: BaseQueryExtraOptions<BaseQuery>,
baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>,
): MaybePromise<QueryReturnValue<ResultType, BaseQueryError<BaseQuery>>>
/* transformResponse only available with `query`, not `queryFn` */
transformResponse?(
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg,
): ResultType | Promise<ResultType>
/* transformErrorResponse only available with `query`, not `queryFn` */
transformErrorResponse?(
baseQueryReturnValue: BaseQueryError<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg,
): unknown
extraOptions?: BaseQueryExtraOptions<BaseQuery>
providesTags?: ResultDescription<
TagTypes,
ResultType,
QueryArg,
BaseQueryError<BaseQuery>
>
keepUnusedDataFor?: number
onQueryStarted?(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryLifecycleApi,
): Promise<void>
onCacheEntryAdded?(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryCacheLifecycleApi,
): Promise<void>
}
變異端點定義
export type MutationDefinition<
QueryArg,
BaseQuery extends BaseQueryFn,
TagTypes extends string,
ResultType,
ReducerPath extends string = string,
Context = Record<string, any>,
> = {
query(arg: QueryArg): BaseQueryArg<BaseQuery>
/* either `query` or `queryFn` can be present, but not both simultaneously */
queryFn(
arg: QueryArg,
api: BaseQueryApi,
extraOptions: BaseQueryExtraOptions<BaseQuery>,
baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>,
): MaybePromise<QueryReturnValue<ResultType, BaseQueryError<BaseQuery>>>
/* transformResponse only available with `query`, not `queryFn` */
transformResponse?(
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg,
): ResultType | Promise<ResultType>
/* transformErrorResponse only available with `query`, not `queryFn` */
transformErrorResponse?(
baseQueryReturnValue: BaseQueryError<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg,
): unknown
extraOptions?: BaseQueryExtraOptions<BaseQuery>
invalidatesTags?: ResultDescription<TagTypes, ResultType, QueryArg>
onQueryStarted?(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
}: MutationLifecycleApi,
): Promise<void>
onCacheEntryAdded?(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
}: MutationCacheLifecycleApi,
): Promise<void>
}
端點如何使用
在定義金鑰時,例如如下所示的 getPosts
,請務必了解此名稱將從 api
匯出,並可以在 api.endpoints.getPosts.useQuery()
、api.endpoints.getPosts.initiate()
和 api.endpoints.getPosts.select()
下參照。mutation
也是如此,但它們參照 useMutation
,而不是 useQuery
。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
providesTags: (result) =>
result ? result.map(({ id }) => ({ type: 'Posts', id })) : [],
}),
addPost: build.mutation<Post, Partial<Post>>({
query: (body) => ({
url: `posts`,
method: 'POST',
body,
}),
invalidatesTags: ['Posts'],
}),
}),
})
// Auto-generated hooks
export const { useGetPostsQuery, useAddPostMutation } = api
// Possible exports
export const { endpoints, reducerPath, reducer, middleware } = api
// reducerPath, reducer, middleware are only used in store configuration
// endpoints will have:
// endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery()
// endpoints.addPost.initiate(), endpoints.addPost.select(), endpoints.addPost.useMutation()
// see `createApi` overview for _all exports_
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
providesTags: (result) =>
result ? result.map(({ id }) => ({ type: 'Posts', id })) : [],
}),
addPost: build.mutation({
query: (body) => ({
url: `posts`,
method: 'POST',
body,
}),
invalidatesTags: ['Posts'],
}),
}),
})
// Auto-generated hooks
export const { useGetPostsQuery, useAddPostMutation } = api
// Possible exports
export const { endpoints, reducerPath, reducer, middleware } = api
// reducerPath, reducer, middleware are only used in store configuration
// endpoints will have:
// endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery()
// endpoints.addPost.initiate(), endpoints.addPost.select(), endpoints.addPost.useMutation()
// see `createApi` overview for _all exports_
extractRehydrationInfo
傳遞給每個已發送動作的函式。如果這傳回 undefined
以外的內容,則該傳回值將用於重新整理已完成和錯誤的查詢。
- TypeScript
- JavaScript
import type { Action, PayloadAction } from '@reduxjs/toolkit'
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { HYDRATE } from 'next-redux-wrapper'
type RootState = any // normally inferred from state
function isHydrateAction(action: Action): action is PayloadAction<RootState> {
return action.type === HYDRATE
}
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
extractRehydrationInfo(action, { reducerPath }): any {
if (isHydrateAction(action)) {
return action.payload[reducerPath]
}
},
endpoints: (build) => ({
// omitted
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { HYDRATE } from 'next-redux-wrapper'
function isHydrateAction(action) {
return action.type === HYDRATE
}
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
extractRehydrationInfo(action, { reducerPath }) {
if (isHydrateAction(action)) {
return action.payload[reducerPath]
}
},
endpoints: (build) => ({
// omitted
}),
})
tagTypes
字串標籤類型名稱陣列。指定標籤類型是選用的,但您應該定義它們,以便它們可用於快取和無效化。在定義標籤類型時,您將能夠在配置 端點 時使用 providesTags
提供它們,並使用 invalidatesTags
宣告它們無效。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Post', 'User'],
endpoints: (build) => ({
// ...endpoints
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Post', 'User'],
endpoints: (build) => ({
// ...endpoints
}),
})
reducerPath
reducerPath
是您的服務將裝載到您的儲存中的唯一金鑰。如果您在應用程式中呼叫 createApi
超過一次,則每次都需要提供唯一值。預設為 'api'
。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const apiOne = createApi({
reducerPath: 'apiOne',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (builder) => ({
// ...endpoints
}),
})
const apiTwo = createApi({
reducerPath: 'apiTwo',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (builder) => ({
// ...endpoints
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
const apiOne = createApi({
reducerPath: 'apiOne',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (builder) => ({
// ...endpoints
}),
})
const apiTwo = createApi({
reducerPath: 'apiTwo',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (builder) => ({
// ...endpoints
}),
})
serializeQueryArgs
如果出於任何原因需要變更快取金鑰的建立,請接受自訂函式。
預設情況下,此函式會採用查詢引數、對適用的物件金鑰進行排序、將結果字串化,並將其與端點名稱串接。這會建立一個基於引數 + 端點名稱組合的快取金鑰(忽略物件金鑰順序),這樣,使用相同引數呼叫任何特定端點都會產生相同的快取金鑰。
keepUnusedDataFor
預設為 60
(此值以秒為單位)。這是 RTK Query 在最後一個元件取消訂閱之後會將您的資料快取多長時間。例如,如果您查詢一個端點,然後卸載元件,然後在給定的時間範圍內載入另一個提出相同要求的元件,最新的值將從快取中提供。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
keepUnusedDataFor: 5,
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
keepUnusedDataFor: 5,
}),
}),
})
refetchOnMountOrArgChange
預設為 false
。這個設定讓您可以控制,如果快取結果已經可用,RTK Query 是否只提供快取結果,或者如果設定為 true
或自上次成功查詢結果以來已經過了一段足夠的時間,是否應該重新擷取
。
false
- 除非查詢尚不存在,否則不會執行查詢。true
- 當新增查詢的新訂閱者時,將會一直重新擷取。行為與呼叫refetch
回呼或在動作建立器中傳遞forceRefetch: true
相同。數字
- 值以秒為單位。如果提供一個數字且快取中有一個現有的查詢,它會比較目前時間與最後完成的時間戳記,並且只在經過足夠時間後才重新擷取。
如果您指定此選項與 skip: true
,則不會評估此選項,直到 skip
為 false 為止。
您可以在 createApi
中設定為全域設定,但您也可以覆寫預設值,並透過將 refetchOnMountOrArgChange
傳遞至每個個別掛勾呼叫,或在發送 initiate
動作時傳遞 forceRefetch: true
來獲得更精細的控制。
refetchOnFocus
預設為 false
。這個設定讓您可以控制,在應用程式視窗重新獲得焦點後,RTK Query 是否會嘗試重新擷取所有已訂閱的查詢。
如果您指定此選項與 skip: true
,則不會評估此選項,直到 skip
為 false 為止。
注意:需要呼叫 setupListeners
。
您可以在 createApi
中設定為全域設定,但您也可以覆寫預設值,並透過將 refetchOnFocus
傳遞至每個個別掛勾呼叫,或在發送 initiate
動作時獲得更精細的控制。
如果您在手動發送查詢時指定 track: false
,RTK Query 將無法自動為您重新擷取。
refetchOnReconnect
預設為 false
。此設定讓您可以控制 RTK Query 是否會在重新連線到網路後嘗試重新擷取所有已訂閱的查詢。
如果您指定此選項與 skip: true
,則不會評估此選項,直到 skip
為 false 為止。
注意:需要呼叫 setupListeners
。
您可以在 createApi
中設定此設定,但您也可以傳遞 refetchOnReconnect
至個別的 hook 呼叫或在發送 initiate
動作時覆寫預設值,以獲得更細緻的控制。
如果您在手動發送查詢時指定 track: false
,RTK Query 將無法自動為您重新擷取。
端點剖析
query
(如果未提供 queryFn
,則為必要)
export type query = <QueryArg>(
arg: QueryArg,
) => string | Record<string, unknown>
// with `fetchBaseQuery`
export type query = <QueryArg>(arg: QueryArg) => string | FetchArgs
query
可以是一個函式,傳回一個 字串
或傳遞至 baseQuery
的 物件
。如果您使用 fetchBaseQuery,它可以傳回 字串
或 FetchArgs
中屬性的 物件
。如果您使用自己的自訂 baseQuery
,您可以依自己的喜好自訂此行為。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Post'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
}),
addPost: build.mutation<Post, Partial<Post>>({
query: (body) => ({
url: `posts`,
method: 'POST',
body,
}),
invalidatesTags: [{ type: 'Post', id: 'LIST' }],
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Post'],
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
}),
addPost: build.mutation({
query: (body) => ({
url: `posts`,
method: 'POST',
body,
}),
invalidatesTags: [{ type: 'Post', id: 'LIST' }],
}),
}),
})
queryFn
(如果未提供 query
,則為必要)
可以用來取代 query
,作為一個內聯函式,完全繞過端點的 baseQuery
。
使用與 baseQuery
相同的引數呼叫,以及提供的 baseQuery
函式本身。預期傳回一個具有 data
或 error
屬性的物件,或一個承諾傳回此類物件的物件。
另請參閱 使用 queryFn 自訂查詢。
queryFn(
arg: QueryArg,
api: BaseQueryApi,
extraOptions: BaseQueryExtraOptions<BaseQuery>,
baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>
): MaybePromise<
| {
error: BaseQueryError<BaseQuery>
data?: undefined
}
| {
error?: undefined
data: ResultType
}
>
export interface BaseQueryApi {
signal: AbortSignal
dispatch: ThunkDispatch<any, any, any>
getState: () => unknown
}
queryFn 函式引數
args
- 在呼叫查詢本身時提供的引數api
-BaseQueryApi
物件,包含signal
、dispatch
和getState
屬性signal
-AbortSignal
物件,可用於中止 DOM 要求和/或讀取要求是否已中止。dispatch
- 對應 Redux 儲存體的store.dispatch
方法getState
- 可呼叫來存取目前儲存狀態的函式
extraOptions
- 為端點提供的extraOptions
屬性的值baseQuery
- 提供給 API 本身的baseQuery
函式
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
}),
flipCoin: build.query<'heads' | 'tails', void>({
queryFn(arg, queryApi, extraOptions, baseQuery) {
const randomVal = Math.random()
if (randomVal < 0.45) {
return { data: 'heads' }
}
if (randomVal < 0.9) {
return { data: 'tails' }
}
return {
error: {
status: 500,
statusText: 'Internal Server Error',
data: "Coin landed on it's edge!",
},
}
},
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
}),
flipCoin: build.query({
queryFn(arg, queryApi, extraOptions, baseQuery) {
const randomVal = Math.random()
if (randomVal < 0.45) {
return { data: 'heads' }
}
if (randomVal < 0.9) {
return { data: 'tails' }
}
return {
error: {
status: 500,
statusText: 'Internal Server Error',
data: "Coin landed on it's edge!",
},
}
},
}),
}),
})
transformResponse
(選擇性,不適用於 queryFn
)
用於處理查詢或突變傳回的資料的函式。
在某些情況下,您可能希望在將資料放入快取前,先操作查詢回傳的資料。在這種情況下,您可以利用 transformResponse
。
另請參閱 使用 transformResponse
自訂查詢回應
transformResponse: (response, meta, arg) =>
response.some.deeply.nested.collection
transformErrorResponse
(選擇性,不適用於 queryFn
)
用於操作失敗的查詢或突變回傳資料的函式。
在某些情況下,您可能希望在將錯誤放入快取前,先操作查詢回傳的錯誤。在這種情況下,您可以利用 transformErrorResponse
。
另請參閱 使用 transformErrorResponse
自訂查詢回應
transformErrorResponse: (response, meta, arg) =>
response.data.some.deeply.nested.errorObject
extraOptions
(選用)
傳遞給提供的 baseQuery
函式的第三個引數
providesTags
(選用,僅適用於查詢端點)
由 query
端點使用。決定哪個「標籤」附加到查詢回傳的快取資料。預期是一個標籤類型字串陣列、一個具有 ID 的標籤類型物件陣列,或一個回傳此類陣列的函式。
['Post']
- 等同於2
[{ type: 'Post' }]
- 等同於1
[{ type: 'Post', id: 1 }]
(result, error, arg) => ['Post']
- 等同於5
(result, error, arg) => [{ type: 'Post' }]
- 等同於4
(result, error, arg) => [{ type: 'Post', id: 1 }]
另請參閱 提供快取資料。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({ type: 'Posts' as const, id })),
{ type: 'Posts', id: 'LIST' },
]
: [{ type: 'Posts', id: 'LIST' }],
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({ type: 'Posts', id })),
{ type: 'Posts', id: 'LIST' },
]
: [{ type: 'Posts', id: 'LIST' }],
}),
}),
})
invalidatesTags
(選用,僅適用於突變端點)
由 mutation
端點使用。決定哪個快取資料應重新擷取或從快取中移除。預期與 providesTags
相同的形狀。
另請參閱 使快取資料失效。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({ type: 'Posts' as const, id })),
{ type: 'Posts', id: 'LIST' },
]
: [{ type: 'Posts', id: 'LIST' }],
}),
addPost: build.mutation<Post, Partial<Post>>({
query(body) {
return {
url: `posts`,
method: 'POST',
body,
}
},
invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({ type: 'Posts', id })),
{ type: 'Posts', id: 'LIST' },
]
: [{ type: 'Posts', id: 'LIST' }],
}),
addPost: build.mutation({
query(body) {
return {
url: `posts`,
method: 'POST',
body,
}
},
invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
}),
}),
})
keepUnusedDataFor
(選用,僅適用於查詢端點)
僅針對此端點覆寫 keepUnusedDataFor
的 API 廣泛定義。
預設為 60
(此值以秒為單位)。這是 RTK Query 在最後一個元件取消訂閱之後會將您的資料快取多長時間。例如,如果您查詢一個端點,然後卸載元件,然後在給定的時間範圍內載入另一個提出相同要求的元件,最新的值將從快取中提供。
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
keepUnusedDataFor: 5,
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',
keepUnusedDataFor: 5,
}),
}),
})
serializeQueryArgs
(選用,僅適用於查詢端點)
可提供以查詢參數為基礎傳回自訂快取金鑰值。
此功能主要用於將非序列化值傳遞為查詢參數物件的一部分,並應從快取金鑰中排除的情況。它也可在端點應僅有一個快取項目時使用,例如無限載入/分頁實作。
與 僅能 傳回字串的 createApi
版本不同,此每端點選項也可以傳回物件、數字或布林值。如果傳回字串,該值將直接用作快取金鑰。如果傳回物件/數字/布林值,該值將傳遞至內建的 defaultSerializeQueryArgs
。這簡化了移除不想包含在快取金鑰中的參數的使用案例。
- TypeScript
- JavaScript
import {
createApi,
fetchBaseQuery,
defaultSerializeQueryArgs,
} from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
interface MyApiClient {
fetchPost: (id: string) => Promise<Post>
}
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
// Example: an endpoint with an API client passed in as an argument,
// but only the item ID should be used as the cache key
getPost: build.query<Post, { id: string; client: MyApiClient }>({
queryFn: async ({ id, client }) => {
const post = await client.fetchPost(id)
return { data: post }
},
serializeQueryArgs: ({ queryArgs, endpointDefinition, endpointName }) => {
const { id } = queryArgs
// This can return a string, an object, a number, or a boolean.
// If it returns an object, number or boolean, that value
// will be serialized automatically via `defaultSerializeQueryArgs`
return { id } // omit `client` from the cache key
// Alternately, you can use `defaultSerializeQueryArgs` yourself:
// return defaultSerializeQueryArgs({
// endpointName,
// queryArgs: { id },
// endpointDefinition
// })
// Or create and return a string yourself:
// return `getPost(${id})`
},
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
// Example: an endpoint with an API client passed in as an argument,
// but only the item ID should be used as the cache key
getPost: build.query({
queryFn: async ({ id, client }) => {
const post = await client.fetchPost(id)
return { data: post }
},
serializeQueryArgs: ({ queryArgs, endpointDefinition, endpointName }) => {
const { id } = queryArgs
// This can return a string, an object, a number, or a boolean.
// If it returns an object, number or boolean, that value
// will be serialized automatically via `defaultSerializeQueryArgs`
return { id } // omit `client` from the cache key
// Alternately, you can use `defaultSerializeQueryArgs` yourself:
// return defaultSerializeQueryArgs({
// endpointName,
// queryArgs: { id },
// endpointDefinition
// })
// Or create and return a string yourself:
// return `getPost(${id})`
},
}),
}),
})
merge
(選用,僅適用於查詢端點)
可提供將傳入的回應值合併至目前的快取資料。如果提供,將不會套用任何自動結構共用 - 由您適當地更新快取。
由於 RTKQ 通常會以新回應取代快取項目,因此您通常需要搭配 serializeQueryArgs
或 forceRefetch
選項使用,以保留現有的快取項目,以便更新。
由於這會與 Immer 結合,因此您可以直接變異 currentCacheValue
,或傳回新值,但不能同時進行。
僅在現有的 currentCacheData
不是 undefined
時才會呼叫 - 在第一次回應時,快取項目只會直接儲存回應資料。
如果您不希望新的要求完全覆寫目前的快取值,這會很有用,可能是因為您已從其他來源手動更新它,而且不希望這些更新遺失。
- TypeScript
- JavaScript
import {
createApi,
fetchBaseQuery,
defaultSerializeQueryArgs,
} from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
listItems: build.query<string[], number>({
query: (pageNumber) => `/listItems?page=${pageNumber}`,
// Only have one cache entry because the arg always maps to one string
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
// Refetch when the page arg changes
forceRefetch({ currentArg, previousArg }) {
return currentArg !== previousArg
},
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
listItems: build.query({
query: (pageNumber) => `/listItems?page=${pageNumber}`,
// Only have one cache entry because the arg always maps to one string
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
// Refetch when the page arg changes
forceRefetch({ currentArg, previousArg }) {
return currentArg !== previousArg
},
}),
}),
})
forceRefetch
(選用,僅適用於查詢端點)
type forceRefetch = (params: {
currentArg: QueryArg | undefined
previousArg: QueryArg | undefined
state: RootState<any, any, string>
endpointState?: QuerySubState<any>
}) => boolean
檢查端點是否應在通常不會的情況下強制重新擷取。這主要用於 RTKQ 保留會隨著時間推移而新增的單一快取項目(與 serializeQueryArgs
傳回固定快取金鑰,以及設定為每次將傳入資料新增至快取項目的 merge
回呼搭配使用)的「無限捲動」/分頁使用案例。
- TypeScript
- JavaScript
import {
createApi,
fetchBaseQuery,
defaultSerializeQueryArgs,
} from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
listItems: build.query<string[], number>({
query: (pageNumber) => `/listItems?page=${pageNumber}`,
// Only have one cache entry because the arg always maps to one string
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
// Refetch when the page arg changes
forceRefetch({ currentArg, previousArg }) {
return currentArg !== previousArg
},
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
listItems: build.query({
query: (pageNumber) => `/listItems?page=${pageNumber}`,
// Only have one cache entry because the arg always maps to one string
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
// Refetch when the page arg changes
forceRefetch({ currentArg, previousArg }) {
return currentArg !== previousArg
},
}),
}),
})
onQueryStarted
(選用)
當您啟動每個個別查詢或突變時會呼叫的函數。此函數會使用包含屬性的生命週期 API 物件呼叫,例如 queryFulfilled
,允許在查詢啟動、成功和失敗時執行程式碼(即在個別查詢/突變呼叫的生命週期中)。
可於 樂觀更新 中的 mutations
使用。
生命週期 API 屬性
dispatch
- 儲存的 dispatch 方法。getState
- 取得儲存目前狀態的方法。extra
-extra
提供為thunk.extraArgument
至configureStore
getDefaultMiddleware
選項。requestId
- 為查詢/突變產生的唯一 ID。queryFulfilled
- 會使用data
屬性(轉換後的查詢結果)和meta
屬性(baseQuery
傳回的meta
)解析的 Promise。如果查詢失敗,此 Promise 會使用錯誤拒絕。這允許您await
查詢完成。getCacheEntry
- 取得快取條目目前值的方法。updateCachedData
(僅限查詢端點) - 接受「配方」回呼的函數,指定如何更新資料,以便在呼叫時更新對應快取的資料。這會在內部使用immer
,且更新可以「可變」撰寫,同時安全地產生下一個不可變狀態。
async function onQueryStarted(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
}: MutationLifecycleApi,
): Promise<void>
async function onQueryStarted(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryLifecycleApi,
): Promise<void>
- TypeScript
- JavaScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
import { messageCreated } from './notificationsSlice'
export interface Post {
id: number
name: string
}
const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
endpoints: (build) => ({
getPost: build.query<Post, number>({
query: (id) => `post/${id}`,
async onQueryStarted(id, { dispatch, queryFulfilled }) {
// `onStart` side-effect
dispatch(messageCreated('Fetching post...'))
try {
const { data } = await queryFulfilled
// `onSuccess` side-effect
dispatch(messageCreated('Post received!'))
} catch (err) {
// `onError` side-effect
dispatch(messageCreated('Error fetching post!'))
}
},
}),
}),
})
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
import { messageCreated } from './notificationsSlice'
const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
endpoints: (build) => ({
getPost: build.query({
query: (id) => `post/${id}`,
async onQueryStarted(id, { dispatch, queryFulfilled }) {
// `onStart` side-effect
dispatch(messageCreated('Fetching post...'))
try {
const { data } = await queryFulfilled
// `onSuccess` side-effect
dispatch(messageCreated('Post received!'))
} catch (err) {
// `onError` side-effect
dispatch(messageCreated('Error fetching post!'))
}
},
}),
}),
})
onCacheEntryAdded
(選用)
當新增新的快取條目時會呼叫的函數,即當建立端點 + 查詢參數組合的新訂閱時。此函數會使用包含屬性的生命週期 API 物件呼叫,例如 cacheDataLoaded
和 cacheDataRemoved
,允許在新增快取條目、載入快取資料和移除快取條目時執行程式碼(即在快取條目的生命週期中)。
可使用於 串流更新。
快取生命週期 API 屬性
dispatch
- 儲存的 dispatch 方法。getState
- 取得儲存目前狀態的方法。extra
-extra
提供為thunk.extraArgument
至configureStore
getDefaultMiddleware
選項。requestId
- 為快取條目產生的唯一 ID。cacheEntryRemoved
- 允許您等待快取條目從快取中移除的時間點的 Promise,方法是不再使用/在應用程式中訂閱太久,或透過 dispatchapi.util.resetApiState
。cacheDataLoaded
- 會使用此快取金鑰的第一個值解析的 Promise。這允許您await
直到快取中出現實際值。
注意:如果快取條目在任何值解析之前從快取中移除,此 Promise 將會以new Error('Promise never resolved before cacheEntryRemoved.')
拒絕,以防止記憶體外洩。你可以重新拋出該錯誤(或完全不處理它) - 它會在cacheEntryAdded
外部被捕捉。getCacheEntry
- 取得快取條目目前值的方法。updateCachedData
(僅查詢端點) - 接受「食譜」回呼的函式,指定在呼叫時如何更新資料。這在內部使用immer
,更新可以「可變地」撰寫,同時安全地產生下一個不可變狀態。
async function onCacheEntryAdded(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
}: MutationCacheLifecycleApi,
): Promise<void>
async function onCacheEntryAdded(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryCacheLifecycleApi,
): Promise<void>
傳回值
請參閱 「已建立的 API」API 參考