本文へスキップ

createApi

createApiはRTK Queryの中核機能です。バックエンドAPIやその他の非同期ソースからデータを取得する方法を記述する一連の「エンドポイント」を定義できます。これには、データの取得と変換方法の設定も含まれます。これにより、データの取得とキャッシュ処理をカプセル化するReduxロジック(およびオプションでReactフック)を含む「APIスライス」構造が生成されます。APIスライス構造

ヒント

通常、アプリケーションが通信する必要がある基本URLごとに、APIスライスは1つだけにする必要があります。例えば、サイトが/api/posts/api/usersの両方からデータを取得する場合、基本URLとして/api/を持つ単一のAPIスライスと、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は、一般的なユースケースのためにfetchを軽量にラップしたfetchBaseQueryというユーティリティをエクスポートしています。クエリのカスタマイズを参照して、fetchBaseQueryが要件を満たさない場合を確認してください。

baseQuery関数の引数

  • args - 指定されたエンドポイントのquery関数の戻り値
  • api - BaseQueryApiオブジェクトは以下を含みます。
    • signal - DOMリクエストの中断に使用できる、またはリクエストの中断済みかどうかを読み取ることができるAbortSignalオブジェクト。
    • 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
}
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

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

endpoints

エンドポイントは、サーバーに対して実行する操作のセットです。ビルダー構文を使用してオブジェクトとして定義します。基本的なエンドポイントタイプには2種類あります。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を参照します。

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に設定されている場合、または最後の成功したクエリ結果から十分な時間が経過している場合にrefetchするかどうかを制御できます。

  • false - まだ存在しない場合以外は、クエリを実行しません。
  • true - クエリの新しいサブスクライバーが追加されると、常に再取得します。refetchコールバックを呼び出すこと、またはアクションクリエーターでforceRefetch: trueを渡すことと同じ動作をします。
  • number - 値は秒単位です。数値が指定されていて、キャッシュに既存のクエリがある場合、現在時刻と最後の成功したタイムスタンプを比較し、十分な時間が経過した場合のみ再取得します。

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を渡すこと、または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 は、string またはbaseQuery に渡されるobject を返す関数にすることができます。 fetchBaseQuery を使用している場合、これは FetchArgs 内のプロパティの string またはobject を返すことができます。独自の baseQuery を使用する場合、この動作を好みに合わせてカスタマイズできます。

query の例
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 関数自体を使用して呼び出されます。data プロパティまたはerror プロパティを持つオブジェクト、またはそのようなオブジェクトを返すpromiseを返すことが期待されます。

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 - signaldispatchgetState プロパティを含むBaseQueryApi オブジェクト
    • signal - DOMリクエストの中断に使用できる、またはリクエストの中断済みかどうかを読み取ることができるAbortSignalオブジェクト。
    • dispatch - 対応するReduxストアのstore.dispatchメソッド。
    • getState - 現在のストアの状態にアクセスするために呼び出すことができる関数。
  • extraOptions - エンドポイントに対して提供されたオプションのextraOptions プロパティの値
  • baseQuery - api 自体に提供されたbaseQuery 関数
Basic 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 関数に3番目の引数として渡されます。

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

(オプション、クエリエンドポイントのみ)

このエンドポイントのみについて、api全体の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,
}),
}),
})

serializeQueryArgs

(オプション、クエリエンドポイントのみ)

クエリ引数に基づいてカスタムキャッシュキー値を返すために提供できます。

これは主に、シリアライズできない値がクエリ引数オブジェクトの一部として渡され、キャッシュキーから除外する必要がある場合に使用されます。エンドポイントが無限スクロール/ページネーションの実装など、単一のキャッシュエントリのみを持つ必要がある場合にも使用できます。

stringのみを返すことができる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 は通常、新しい応答でキャッシュエントリを置き換えるため、通常はserializeQueryArgs またはforceRefetch オプションと共にこれを使用する必要があります。これにより、既存のキャッシュエントリを維持して更新できるようになります。

これは Immer でラップされているため、currentCacheValue を直接変更するか、新しい値を返すことができますが、両方同時にはできません

既存のcurrentCacheDataundefined ではない場合にのみ呼び出されます。最初の応答では、キャッシュエントリは応答データを直接保存します。

別のソースから手動で更新したため、それらの更新が失われないようにする場合など、新しいリクエストによって現在のキャッシュ値が完全に上書きされないようにする場合に役立ちます。

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
},
}),
}),
})

forceRefetch

(オプション、クエリエンドポイントのみ)

forceRefetch のシグネチャ
type forceRefetch = (params: {
currentArg: QueryArg | undefined
previousArg: QueryArg | undefined
state: RootState<any, any, string>
endpointState?: QuerySubState<any>
}) => boolean

通常は行わない場合に、エンドポイントが強制的に再フェッチする必要があるかどうかを確認します。これは主に、RTKQ が時間とともに追加される単一のキャッシュエントリを保持する「無限スクロール」/ページネーションのユースケースで、serializeQueryArgs が固定されたキャッシュキーを返し、merge コールバックが設定されて各回キャッシュエントリに受信データを追加する場合に役立ちます。

forceRefresh: ページネーション
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

(オプション)

クエリミューテーションの両方で使用できます。

個々のクエリまたはミューテーションを開始するときに呼び出される関数。この関数は、queryFulfilled などのプロパティを含むライフサイクル api オブジェクトを使用して呼び出され、クエリが開始されたとき、成功したとき、失敗したとき(つまり、個々のクエリ/ミューテーション呼び出しのライフサイクル全体)にコードを実行できます。

楽観的更新のためにmutations で使用できます。

ライフサイクルAPIのプロパティ

  • dispatch - ストアのためのディスパッチメソッド。
  • getState - ストアの現在の状態を取得するためのメソッド。
  • extra - configureStoregetDefaultMiddleware オプションにthunk.extraArgument として提供されたextra
  • 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

(オプション)

クエリミューテーションの両方で使用できます。

新しいキャッシュエントリが追加されたとき、つまり、エンドポイントとクエリパラメータの組み合わせの新しいサブスクリプションが作成されたときに呼び出される関数。この関数は、cacheDataLoadedcacheDataRemoved などのプロパティを含むライフサイクル api オブジェクトを使用して呼び出され、キャッシュエントリが追加されたとき、キャッシュデータが読み込まれたとき、キャッシュエントリが削除されたとき(つまり、キャッシュエントリのライフサイクル全体)にコードを実行できます。

ストリーミング更新に使用できます。

キャッシュライフサイクルAPIのプロパティ

  • dispatch - ストアのためのディスパッチメソッド。
  • getState - ストアの現在の状態を取得するためのメソッド。
  • extra - configureStoregetDefaultMiddleware オプションにthunk.extraArgument として提供されたextra
  • requestId - キャッシュエントリに対して生成された一意のID。
  • cacheEntryRemoved - アプリケーションで長すぎる間使用/購読されていないか、api.util.resetApiState をディスパッチすることで、キャッシュエントリがキャッシュから削除された時点を待機できる Promise。
  • 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リファレンスを参照してください