Skip to content

Assorted pre-2.8 docs tweaks #4968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api/createEntityAdapter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ If `updateMany()` is called with multiple updates targeted to the same ID, they

For both `updateOne()` and `updateMany()`, changing the ID of one existing entity to match the ID of a second existing entity will cause the first to replace the second completely.

Additionally, if there is no item for that ID, the update will be silently ignored.

## Examples

Exercising several of the CRUD methods and selectors:
Expand Down
26 changes: 26 additions & 0 deletions docs/rtk-query/api/createApi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,32 @@ Query endpoints (defined with `build.query()`) are used to cache data fetched fr
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 FullTagDescription<TagType> = {
type: TagType
id?: number | string
}
export type TagDescription<TagType> = TagType | FullTagDescription<TagType>

type TagDescriptionArray<TagTypes extends string> = ReadonlyArray<
TagDescription<TagTypes> | undefined | null
>

export type ResultDescription<
TagTypes extends string,
ResultType,
QueryArg,
ErrorType,
MetaType,
> =
| TagDescriptionArray<TagTypes>
| (
result: ResultType | undefined,
error: ErrorType | undefined,
arg: QueryArg,
meta: MetaType,
) => TagDescriptionArray<TagTypes>


export type QueryDefinition<
QueryArg,
BaseQuery extends BaseQueryFn,
Expand Down
69 changes: 66 additions & 3 deletions docs/rtk-query/usage/code-splitting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ description: 'RTK Query > Usage > Code Splitting: dynamic injection of endpoints

# Code Splitting

RTK Query makes it possible to trim down your initial bundle size by allowing you to inject additional endpoints after you've set up your initial service definition. This can be very beneficial for larger applications that may have _many_ endpoints.
## Overview

`injectEndpoints` accepts a collection of endpoints, as well as an optional `overrideExisting` parameter.
By default, an RTK Query API definition normally has all of the endpoint definitions in a single file. However, in larger applications this can result in very large files that may be harder to maintain. It also means that all of the relevant code is being imported right away.

Calling `injectEndpoints` will inject the endpoints into the original API, but also give you that same API with correct types for these endpoints back. (Unfortunately, it cannot modify the types for the original definition.)
RTK Query allows dynamically injecting endpoint definitions into an existing API service object. This enables splitting up endpoints into multiple files for maintainability, as well as lazy-loading endpoint definitions and associated code to trim down initial bundle sizes. This can be very beneficial for larger applications that may have _many_ endpoints.

## Injecting Endpoints

`api.injectEndpoints` accepts a collection of endpoint definitions (same as `createApi`), as well as an optional `overrideExisting` parameter.

Calling `api.injectEndpoints` will inject the endpoints into the original API service object, modifying it immediately. It returns **the _same_ API service object reference**. If you're using TypeScript, the return value has the TS types for the new endpoints included. (Unfortunately, it cannot modify the types for the original API reference.)

A typical approach would be to have one empty central API slice definition:

Expand Down Expand Up @@ -43,6 +49,7 @@ export const emptySplitApi = createApi({
// file: extendedApi.ts
import { emptySplitApi } from './emptySplitApi'

// NOTE: these are the _SAME_ API reference!
const extendedApi = emptySplitApi.injectEndpoints({
endpoints: (build) => ({
example: build.query({
Expand All @@ -60,3 +67,59 @@ If you inject an endpoint that already exists and don't explicitly specify `over
will not be overridden. In development mode, you will get a warning about this if `overrideExisting` is set to `false`,
and an error will be throw if set to `'throw'`.
:::

## Enhancing Endpoints

Sometimes you may also need to modify an existing API definition, such as adding additional tag types, or providing additional configuration options to a given endpoint.

`api.enhanceEndpoints` returns an updated and enhanced version of the API slice object, containing the combined endpoint definitions.

This is primarily useful for taking an API slice object that was code-generated from an API schema file like OpenAPI, and adding additional specific hand-written configuration for cache invalidation management on top of the generated endpoint definitions.

For example, `enhanceEndpoints` can be used to modify caching behavior by changing the values of `providesTags`, `invalidatesTags`, and `keepUnusedDataFor`:

```ts
// file: api.ts noEmit
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getUserByUserId: build.query({
query() {
return ''
},
}),
patchUserByUserId: build.mutation({
query() {
return ''
},
}),
getUsers: build.query({
query() {
return ''
},
}),
}),
})

// file: enhanceEndpoints.ts
import { api } from './api'

const enhancedApi = api.enhanceEndpoints({
addTagTypes: ['User'],
endpoints: {
getUserByUserId: {
providesTags: ['User'],
},
patchUserByUserId: {
invalidatesTags: ['User'],
},
// alternatively, define a function which is called with the endpoint definition as an argument
getUsers(endpoint) {
endpoint.providesTags = ['User']
endpoint.keepUnusedDataFor = 120
},
},
})
```
24 changes: 14 additions & 10 deletions packages/toolkit/src/query/core/apiState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ export type RefetchConfigOptions = {
refetchOnFocus: boolean
}

export type PageParamFunction<DataType, PageParam, QueryArg> = (
firstPage: DataType,
allPages: Array<DataType>,
firstPageParam: PageParam,
allPageParams: Array<PageParam>,
queryArg: QueryArg,
) => PageParam | undefined | null

export type InfiniteQueryConfigOptions<DataType, PageParam, QueryArg> = {
/**
* The initial page parameter to use for the first page fetch.
Expand All @@ -42,12 +34,24 @@ export type InfiniteQueryConfigOptions<DataType, PageParam, QueryArg> = {
* 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<DataType, PageParam, QueryArg>
getNextPageParam: (
lastPage: DataType,
allPages: Array<DataType>,
lastPageParam: PageParam,
allPageParams: Array<PageParam>,
queryArg: QueryArg,
) => PageParam | undefined | null
/**
* 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<DataType, PageParam, QueryArg>
getPreviousPageParam?: (
firstPage: DataType,
allPages: Array<DataType>,
firstPageParam: PageParam,
allPageParams: Array<PageParam>,
queryArg: QueryArg,
) => PageParam | undefined | null
/**
* If specified, only keep this many pages in cache at once.
* If additional pages are fetched, older pages in the other
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/src/query/core/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,13 +471,13 @@ export interface ApiEndpointMutation<
export type ListenerActions = {
/**
* Will cause the RTK Query middleware to trigger any refetchOnReconnect-related behavior
* @link https://rtk-query-docs.netlify.app/api/setupListeners
* @link https://redux-toolkit.js.org/rtk-query/api/setupListeners
*/
onOnline: typeof onOnline
onOffline: typeof onOffline
/**
* Will cause the RTK Query middleware to trigger any refetchOnFocus-related behavior
* @link https://rtk-query-docs.netlify.app/api/setupListeners
* @link https://redux-toolkit.js.org/rtk-query/api/setupListeners
*/
onFocus: typeof onFocus
onFocusLost: typeof onFocusLost
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/src/query/createApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ export type CreateApi<Modules extends ModuleName> = {
/**
* Creates a service to use in your application. Contains only the basic redux logic (the core module).
*
* @link https://rtk-query-docs.netlify.app/api/createApi
* @link https://redux-toolkit.js.org/rtk-query/api/createApi
*/
<
BaseQuery extends BaseQueryFn,
Expand All @@ -320,7 +320,7 @@ export type CreateApi<Modules extends ModuleName> = {
/**
* Builds a `createApi` method based on the provided `modules`.
*
* @link https://rtk-query-docs.netlify.app/concepts/customizing-create-api
* @link https://redux-toolkit.js.org/rtk-query/usage/customizing-create-api
*
* @example
* ```ts
Expand Down
8 changes: 6 additions & 2 deletions packages/toolkit/src/query/endpointDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ export enum DefinitionType {
infinitequery = 'infinitequery',
}

type TagDescriptionArray<TagTypes extends string> = ReadonlyArray<
TagDescription<TagTypes> | undefined | null
>

export type GetResultDescriptionFn<
TagTypes extends string,
ResultType,
Expand All @@ -488,7 +492,7 @@ export type GetResultDescriptionFn<
error: ErrorType | undefined,
arg: QueryArg,
meta: MetaType,
) => ReadonlyArray<TagDescription<TagTypes> | undefined | null>
) => TagDescriptionArray<TagTypes>

export type FullTagDescription<TagType> = {
type: TagType
Expand All @@ -506,7 +510,7 @@ export type ResultDescription<
ErrorType,
MetaType,
> =
| ReadonlyArray<TagDescription<TagTypes> | undefined | null>
| TagDescriptionArray<TagTypes>
| GetResultDescriptionFn<TagTypes, ResultType, QueryArg, ErrorType, MetaType>

type QueryTypes<
Expand Down
1 change: 1 addition & 0 deletions packages/toolkit/src/query/react/buildHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,7 @@ export type UseInfiniteQueryStateOptions<
* `selectFromResult` allows you to get a specific segment from a query result in a performant manner.
* When using this feature, the component will not rerender unless the underlying data of the selected item has changed.
* If the selected item is one element in a larger collection, it will disregard changes to elements in the same collection.
* Note that this should always return an object (not a primitive), as RTKQ adds fields to the return value.
*
* @example
* ```ts
Expand Down
Loading