API: createApi reference">API: createApi reference">
跳至主要內容

createApi

createApi 是 RTK Query 功能的核心。它允許您定義一組「端點」,用來描述如何從後端 API 和其他非同步來源擷取資料,包括如何擷取和轉換資料的設定。它會產生一個「API 區段結構」,其中包含 Redux 邏輯(以及 React hooks,視情況而定),可為您封裝資料擷取和快取處理程序。

提示

通常,每個應用程式需要通訊的基礎 URL,你應該只有一個 API 切片。例如,如果你的網站從 /api/posts/api/users 取得資料,你會有一個單一的 API 切片,其中 /api/ 是基礎 URL,並針對 postsusers 分別定義端點。這可讓你可以有效利用 自動重新取得,方法是在端點之間定義 標籤 關係。

為了維護性,你可能希望將端點定義分割成多個檔案,同時仍維護包含所有這些端點的單一 API 切片。請參閱 程式碼分割,了解如何使用 injectEndpoints 屬性將其他檔案的 API 端點注入到單一 API 切片定義中。

範例:src/services/pokemon.ts
// 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

參數

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 - 要求類型(querymutation)。
    • 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
}
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
// ...endpoints
}),
})

endpoints

端點只是您想對伺服器執行的操作集合。您可以使用建構器語法將它們定義為物件。有兩種基本端點類型:querymutation

有關個別屬性的詳細資訊,請參閱 端點解剖

查詢端點定義

查詢端點定義
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

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_

extractRehydrationInfo

傳遞給每個已發送動作的函式。如果這傳回 undefined 以外的內容,則該傳回值將用於重新整理已完成和錯誤的查詢。

next-redux-wrapper 重新整理範例
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
}),
})

另請參閱 伺服器端呈現持久性和重新整理

tagTypes

字串標籤類型名稱陣列。指定標籤類型是選用的,但您應該定義它們,以便它們可用於快取和無效化。在定義標籤類型時,您將能夠在配置 端點 時使用 providesTags 提供它們,並使用 invalidatesTags 宣告它們無效。

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

const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Post', 'User'],
endpoints: (build) => ({
// ...endpoints
}),
})

reducerPath

reducerPath 是您的服務將裝載到您的儲存中的唯一金鑰。如果您在應用程式中呼叫 createApi 超過一次,則每次都需要提供唯一值。預設為 'api'

apis.js
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 在最後一個元件取消訂閱之後會將您的資料快取多長時間。例如,如果您查詢一個端點,然後卸載元件,然後在給定的時間範圍內載入另一個提出相同要求的元件,最新的值將從快取中提供。

keepUnusedDataFor 範例
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,
}),
}),
})

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,您可以依自己的喜好自訂此行為。

查詢範例
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' }],
}),
}),
})

queryFn

(如果未提供 query,則為必要)

可以用來取代 query,作為一個內聯函式,完全繞過端點的 baseQuery

使用與 baseQuery 相同的引數呼叫,以及提供的 baseQuery 函式本身。預期傳回一個具有 dataerror 屬性的物件,或一個承諾傳回此類物件的物件。

另請參閱 使用 queryFn 自訂查詢

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 物件,包含 signaldispatchgetState 屬性
    • signal - AbortSignal 物件,可用於中止 DOM 要求和/或讀取要求是否已中止。
    • dispatch - 對應 Redux 儲存體的 store.dispatch 方法
    • getState - 可呼叫來存取目前儲存狀態的函式
  • extraOptions - 為端點提供的 extraOptions 屬性的值
  • baseQuery - 提供給 API 本身的 baseQuery 函式
基本 queryFn 範例
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!",
},
}
},
}),
}),
})

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 的標籤類型物件陣列,或一個回傳此類陣列的函式。

  1. ['Post'] - 等同於 2
  2. [{ type: 'Post' }] - 等同於 1
  3. [{ type: 'Post', id: 1 }]
  4. (result, error, arg) => ['Post'] - 等同於 5
  5. (result, error, arg) => [{ type: 'Post' }] - 等同於 4
  6. (result, error, arg) => [{ type: 'Post', id: 1 }]

另請參閱 提供快取資料

providesTags 範例
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' }],
}),
}),
})

invalidatesTags

(選用,僅適用於突變端點)

mutation 端點使用。決定哪個快取資料應重新擷取或從快取中移除。預期與 providesTags 相同的形狀。

另請參閱 使快取資料失效

invalidatesTags 範例
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' }],
}),
}),
})

keepUnusedDataFor

(選用,僅適用於查詢端點)

僅針對此端點覆寫 keepUnusedDataFor 的 API 廣泛定義。

預設為 60 (此值以秒為單位)。這是 RTK Query 在最後一個元件取消訂閱之後會將您的資料快取多長時間。例如,如果您查詢一個端點,然後卸載元件,然後在給定的時間範圍內載入另一個提出相同要求的元件,最新的值將從快取中提供。

keepUnusedDataFor 範例
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,
}),
}),
})

serializeQueryArgs

(選用,僅適用於查詢端點)

可提供以查詢參數為基礎傳回自訂快取金鑰值。

此功能主要用於將非序列化值傳遞為查詢參數物件的一部分,並應從快取金鑰中排除的情況。它也可在端點應僅有一個快取項目時使用,例如無限載入/分頁實作。

僅能 傳回字串的 createApi 版本不同,此每端點選項也可以傳回物件、數字或布林值。如果傳回字串,該值將直接用作快取金鑰。如果傳回物件/數字/布林值,該值將傳遞至內建的 defaultSerializeQueryArgs。這簡化了移除不想包含在快取金鑰中的參數的使用案例。

serializeQueryArgs:排除值
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})`
},
}),
}),
})

merge

(選用,僅適用於查詢端點)

可提供將傳入的回應值合併至目前的快取資料。如果提供,將不會套用任何自動結構共用 - 由您適當地更新快取。

由於 RTKQ 通常會以新回應取代快取項目,因此您通常需要搭配 serializeQueryArgsforceRefetch 選項使用,以保留現有的快取項目,以便更新。

由於這會與 Immer 結合,因此您可以直接變異 currentCacheValue,或傳回新值,但不能同時進行。

僅在現有的 currentCacheData 不是 undefined 時才會呼叫 - 在第一次回應時,快取項目只會直接儲存回應資料。

如果您不希望新的要求完全覆寫目前的快取值,這會很有用,可能是因為您已從其他來源手動更新它,而且不希望這些更新遺失。

合併:分頁
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
},
}),
}),
})

forceRefetch

(選用,僅適用於查詢端點)

forceRefetch 簽章
type forceRefetch = (params: {
currentArg: QueryArg | undefined
previousArg: QueryArg | undefined
state: RootState<any, any, string>
endpointState?: QuerySubState<any>
}) => boolean

檢查端點是否應在通常不會的情況下強制重新擷取。這主要用於 RTKQ 保留會隨著時間推移而新增的單一快取項目(與 serializeQueryArgs 傳回固定快取金鑰,以及設定為每次將傳入資料新增至快取項目的 merge 回呼搭配使用)的「無限捲動」/分頁使用案例。

強制重新整理:分頁
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
},
}),
}),
})

onQueryStarted

(選用)

適用於 查詢突變

當您啟動每個個別查詢或突變時會呼叫的函數。此函數會使用包含屬性的生命週期 API 物件呼叫,例如 queryFulfilled,允許在查詢啟動、成功和失敗時執行程式碼(即在個別查詢/突變呼叫的生命週期中)。

可於 樂觀更新 中的 mutations 使用。

生命週期 API 屬性

  • dispatch - 儲存的 dispatch 方法。
  • getState - 取得儲存目前狀態的方法。
  • extra - extra 提供為 thunk.extraArgumentconfigureStore getDefaultMiddleware 選項。
  • requestId - 為查詢/突變產生的唯一 ID。
  • queryFulfilled - 會使用 data 屬性(轉換後的查詢結果)和 meta 屬性(baseQuery 傳回的 meta)解析的 Promise。如果查詢失敗,此 Promise 會使用錯誤拒絕。這允許您 await 查詢完成。
  • getCacheEntry - 取得快取條目目前值的方法。
  • updateCachedData (僅限查詢端點) - 接受「配方」回呼的函數,指定如何更新資料,以便在呼叫時更新對應快取的資料。這會在內部使用 immer,且更新可以「可變」撰寫,同時安全地產生下一個不可變狀態。
onQueryStarted 突變簽章
async function onQueryStarted(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
}: MutationLifecycleApi,
): Promise<void>
onQueryStarted 查詢簽章
async function onQueryStarted(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryLifecycleApi,
): Promise<void>
onQueryStarted 查詢生命週期範例
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!'))
}
},
}),
}),
})

onCacheEntryAdded

(選用)

適用於 查詢突變

當新增新的快取條目時會呼叫的函數,即當建立端點 + 查詢參數組合的新訂閱時。此函數會使用包含屬性的生命週期 API 物件呼叫,例如 cacheDataLoadedcacheDataRemoved,允許在新增快取條目、載入快取資料和移除快取條目時執行程式碼(即在快取條目的生命週期中)。

可使用於 串流更新

快取生命週期 API 屬性

  • dispatch - 儲存的 dispatch 方法。
  • getState - 取得儲存目前狀態的方法。
  • extra - extra 提供為 thunk.extraArgumentconfigureStore getDefaultMiddleware 選項。
  • requestId - 為快取條目產生的唯一 ID。
  • cacheEntryRemoved - 允許您等待快取條目從快取中移除的時間點的 Promise,方法是不再使用/在應用程式中訂閱太久,或透過 dispatch api.util.resetApiState
  • cacheDataLoaded - 會使用此快取金鑰的第一個值解析的 Promise。這允許您 await 直到快取中出現實際值。
    注意:如果快取條目在任何值解析之前從快取中移除,此 Promise 將會以 new Error('Promise never resolved before cacheEntryRemoved.') 拒絕,以防止記憶體外洩。你可以重新拋出該錯誤(或完全不處理它) - 它會在 cacheEntryAdded 外部被捕捉。
  • getCacheEntry - 取得快取條目目前值的方法。
  • updateCachedData (僅查詢端點) - 接受「食譜」回呼的函式,指定在呼叫時如何更新資料。這在內部使用 immer,更新可以「可變地」撰寫,同時安全地產生下一個不可變狀態。
onCacheEntryAdded 突變簽章
async function onCacheEntryAdded(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
}: MutationCacheLifecycleApi,
): Promise<void>
onCacheEntryAdded 查詢簽章
async function onCacheEntryAdded(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
updateCachedData, // available for query endpoints only
}: QueryCacheLifecycleApi,
): Promise<void>

傳回值

請參閱 「已建立的 API」API 參考