diff --git a/docs/rtk-query/api/createApi.mdx b/docs/rtk-query/api/createApi.mdx index 76a75de5f7..eb21d2d7de 100644 --- a/docs/rtk-query/api/createApi.mdx +++ b/docs/rtk-query/api/createApi.mdx @@ -148,6 +148,10 @@ See [Endpoint Definition Parameters](#endpoint-definition-parameters) for detail #### Query endpoint definition +Query endpoints (defined with `builder.query()`) are used to cache data fetched from the server. + +You must specify either a `query` field (which will use the API's `baseQuery` to make a request), or a `queryFn` function with your own async logic. All other fields are optional. + ```ts title="Query endpoint definition" no-transpile export type QueryDefinition< QueryArg, @@ -220,8 +224,70 @@ export type QueryDefinition< } ``` +#### Infinite Query endpoint definition + +Infinite query endpoints (defined with `builder.infiniteQuery()`) are used to cache multi-page data sets from the server. They have all the same callbacks and options as standard query endpoints, but also require an additional [`infiniteQueryOptions`](#infinitequeryoptions) field to specify how to calculate the unique parameters to fetch each page. + +For infinite query endpoints, there is a separation between the "query arg" used for the cache key, and the "page param" used to fetch a specific page. For example, a Pokemon API endpoint might have a string query arg like `"fire"` as the query arg, but use a page number as the param to determine which page to fetch out of the results. This means the page param is what will be passed to your `query` or `queryFn` methods. + +```ts title="Infinite Query endpoint definition" no-transpile +export type PageParamFunction = ( + firstPage: DataType, + allPages: Array, + firstPageParam: PageParam, + allPageParams: Array, +) => PageParam | undefined | null + +export type InfiniteQueryDefinition< + QueryArg, + PageParam, + BaseQuery extends BaseQueryFn, + TagTypes extends string, + ResultType, + ReducerPath extends string = string, +> = + // Infinite queries have all the same options as query endpoints, + // but store the `{data, pages}` structure, and use the + // `PageParam` type as the `QueryArg` for fetching. + QueryDefinition> & { + /** + * Required options to configure the infinite query behavior. + * `initialPageParam` and `getNextPageParam` are required, to + * ensure the infinite query can properly fetch the next page of data. + * `initialPageparam` may be specified when using the + * endpoint, to override the default value. + */ + infiniteQueryOptions: { + /** + * The initial page parameter to use for the first page fetch. + */ + initialPageParam: PageParam + /** + * If specified, only keep this many pages in cache at once. + * If additional pages are fetched, older pages in the other + * direction will be dropped from the cache. + */ + maxPages?: number + /** + * This function can be set to automatically get the previous cursor for infinite queries. + * The result will also be used to determine the value of `hasPreviousPage`. + */ + getPreviousPageParam?: PageParamFunction + /** + * This function is required to automatically get the next cursor for infinite queries. + * The result will also be used to determine the value of `hasNextPage`. + */ + getNextPageParam: PageParamFunction + } + } +``` + #### Mutation endpoint definition +Mutation endpoints (defined with `builder.mutation()`) are used to send updates to the server, and force invalidation and refetching of query endpoints. + +As with queries, you must specify either the `query` option or the `queryFn` async method. + ```ts title="Mutation endpoint definition" no-transpile export type MutationDefinition< QueryArg, @@ -446,7 +512,7 @@ export interface BaseQueryApi { } ``` -#### queryFn function arguments +#### `queryFn` function arguments - `args` - The argument provided when the query itself is called - `api` - The `BaseQueryApi` object, containing `signal`, `dispatch` and `getState` properties @@ -458,6 +524,21 @@ export interface BaseQueryApi { [examples](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQueryFn.queryFn) +### `infiniteQueryOptions` + +_(only for `infiniteQuery` endpoints)_ + +[summary](docblock://query/endpointDefinitions.ts?token=InfiniteQueryExtraOptions.infiniteQueryOptions) + +The `infiniteQueryOptions` field includes: + +- `initialPageParam`: the default page param value used for the first request, if this was not specified at the usage site +- `maxPages`: an optional limit to how many fetched pages will be kept in the cache entry at a time +- `getNextPageParam`: a required callback you must provide to calculate the next page param, given the existing cached pages and page params +- `getPreviousPageParam`: an optional callback that will be used to calculate the previous page param, if you try to fetch backwards. + +[examples](docblock://query/endpointDefinitions.ts?token=InfiniteQueryExtraOptions.infiniteQueryOptions) + ### `transformResponse` _(optional, not applicable with `queryFn`)_ diff --git a/packages/toolkit/src/query/createApi.ts b/packages/toolkit/src/query/createApi.ts index 1d0ab4a1a5..9112baffc8 100644 --- a/packages/toolkit/src/query/createApi.ts +++ b/packages/toolkit/src/query/createApi.ts @@ -98,7 +98,7 @@ export interface CreateApiOptions< */ serializeQueryArgs?: SerializeQueryArgs /** - * Endpoints are a set of operations that you want to perform against your server. You define them as an object using the builder syntax. There are two basic endpoint types: [`query`](../../rtk-query/usage/queries) and [`mutation`](../../rtk-query/usage/mutations). + * Endpoints are a set of operations that you want to perform against your server. You define them as an object using the builder syntax. There are three endpoint types: [`query`](../../rtk-query/usage/queries), [`infiniteQuery`](../../rtk-query/usage/infinite-queries) and [`mutation`](../../rtk-query/usage/mutations). */ endpoints( build: EndpointBuilder, diff --git a/packages/toolkit/src/query/endpointDefinitions.ts b/packages/toolkit/src/query/endpointDefinitions.ts index 0825a6061e..8c9acbca97 100644 --- a/packages/toolkit/src/query/endpointDefinitions.ts +++ b/packages/toolkit/src/query/endpointDefinitions.ts @@ -604,8 +604,42 @@ export interface InfiniteQueryExtraOptions< /** * Required options to configure the infinite query behavior. * `initialPageParam` and `getNextPageParam` are required, to - * ensure the infinite query can properly fetch the next page of data. `initialPageparam` may be specified when using the + * ensure the infinite query can properly fetch the next page of data. + * `initialPageParam` may be specified when using the * endpoint, to override the default value. + * + * @example + * + * ```ts + * // codeblock-meta title="infiniteQueryOptions example" + * getInfinitePokemonWithMax: builder.infiniteQuery< + Pokemon[], + string, + number + >({ + infiniteQueryOptions: { + initialPageParam: 0, + maxPages: 3, + getNextPageParam: ( + lastPage, + allPages, + lastPageParam, + allPageParams, + ) => lastPageParam + 1, + getPreviousPageParam: ( + firstPage, + allPages, + firstPageParam, + allPageParams, + ) => { + return firstPageParam > 0 ? firstPageParam - 1 : undefined + }, + }, + query(pageParam) { + return `https://example.com/listItems?page=${pageParam}` + }, + }), + * ``` */ infiniteQueryOptions: InfiniteQueryConfigOptions @@ -691,7 +725,7 @@ export type InfiniteQueryDefinition< ResultType, ReducerPath extends string = string, > = - // Intentionally use `PageParam` as the QueryArg` type + // Intentionally use `PageParam` as the `QueryArg` type BaseEndpointDefinition & InfiniteQueryExtraOptions< TagTypes, diff --git a/packages/toolkit/src/query/react/buildHooks.ts b/packages/toolkit/src/query/react/buildHooks.ts index 9923b23990..d9092848fc 100644 --- a/packages/toolkit/src/query/react/buildHooks.ts +++ b/packages/toolkit/src/query/react/buildHooks.ts @@ -65,7 +65,7 @@ import { useStableQueryArgs } from './useSerializedStableValue' import { useShallowStableValue } from './useShallowStableValue' import type { InfiniteQueryDirection } from '../core/apiState' import { isInfiniteQueryDefinition } from '../endpointDefinitions' -import { StartInfiniteQueryActionCreator } from '../core/buildInitiate' +import type { StartInfiniteQueryActionCreator } from '../core/buildInitiate' // Copy-pasted from React-Redux const canUseDOM = () =>