reduxjs/redux-toolkit
github.com/reduxjs/redux-toolkit ↗ · 923 files · 4.1 MB
Redux Toolkit docs The pages in this folder are published as part of the combined Redux docs site, at https://redux.js.org/toolkit.
Overview
Redux Toolkit is a TypeScript library monorepo for developers building Redux applications, with APIs for store configuration, immutable reducers, normalized entities, and asynchronous workflows. Its optional RTK Query entrypoints turn endpoint definitions into Redux-backed request caches, lifecycle utilities, and React hooks. The repository also contains OpenAPI code generation, GraphQL transport integration, migration codemods, documentation, and application fixtures that exercise package compatibility.
System map
The main product is a set of published library entrypoints consumed by application stores. RTK Query separates framework-independent request machinery from React hook generation. Redux state and middleware-local maps have distinct ownership responsibilities. Build configuration emits several module formats, while documentation deployment incorporates this checkout into the separate Redux website.
- @reduxjs/toolkit exposes four public entrypoints: the root, /react, /query, and /query/react, with conditional module-sync, browser, React Native, import, and CommonJS resolution.
- The root entrypoint exports store, slice, thunk, entity, listener, dynamic middleware, and batching APIs; /react reexports the root and adds React-specific dynamic middleware.
- React createApi is assembled by buildCreateApi(coreModule(), reactHooksModule()); the query entrypoint exposes core createApi without requiring generated React hooks.
- coreModule initializes selectors, thunks, slices, initiation functions, and middleware, then attaches endpoint select/initiate functions and thunk matchers.
- API Redux state combines queries, mutations, provided tags, subscriptions, and config; a WeakMap keyed by dispatch separately holds subscription, polling, and running-request maps.
- The pnpm workspace includes packages, docs, infinite-query examples, and type-portability fixtures. Root build/test scripts recursively filter @reduxjs/* and @rtk-query/*; workspace dependency linking is disabled.
- tsdown builds separate nested entrypoints without shared chunks, externalizes Redux/React/Immer dependencies, and emits modern ESM, development/production CJS, browser ESM, legacy ESM, and declaration variants.
- Documentation pages live here, but the Docusaurus website lives in reduxjs/redux. Netlify previews build Toolkit and the combined site using DOCS_SOURCE_REDUX_TOOLKIT; production publishes redirects to redux.js.org/toolkit.
Feature catalog
The user-facing product consists primarily of programming APIs and developer tooling. Store and reducer helpers address application-owned state, while RTK Query handles server-state requests and cache coordination. React examples expose fetching, editing, authentication, polling, and pagination interfaces. This catalog describes inspected capabilities and routes rather than claiming exhaustive coverage of every fixture.
- configureStore accepts a root reducer or reducer map, preloadedState, middleware/enhancer callbacks, and DevTools options; defaults include thunk middleware and automatic batching.
- createSlice produces actions, caseReducers, initial-state access, selectors, and injectInto; createReducer handles action cases and matchers with draft-aware immutable updates.
- createEntityAdapter supplies state factories, selectors, and entity operations, choosing a sorted or unsorted implementation from sortComparer and using instance.id unless selectId is supplied.
- createAsyncThunk exposes pending/fulfilled/rejected actions, abort and unwrap handles; listener effects additionally receive condition, take, delay, pause, fork, and cancellation controls.
- RTK Query supports query, mutation, and infiniteQuery definitions, generated query/lazy-query/mutation/infinite-query hooks, usePrefetch, optimistic cache updates, and optional retry wrapping.
- The inspected React demos include Pokémon loading/error display, post POST/PUT/DELETE operations with rollback, and /login plus a guarded index route; kitchen-sink exposes times, counters, posts, and bundle splitting.
- The infinite-query showcase routes cover pagination, infinite scroll, bounded pages, bidirectional cursors, limit/offset, pagination with infinite scroll, and RN FlatList; type-portability apps reproduce the times/posts/counters/bundle-splitting surface across module modes.
- Companion tooling includes graphqlRequestBaseQuery, the rtk-query-codegen-openapi CLI with configurable hooks/tags/naming/encoding, and a codemod CLI that selects TypeScript transforms such as createSliceBuilder.
Data flow
Application arguments enter endpoint initiation and become serialized cache keys before request execution. Endpoint query functions translate arguments into transport inputs, while optional schemas and transforms shape results before Redux receives them. Hooks select cached state and manage subscriptions rather than owning the shared response cache. Rehydration and code generation introduce separate application-action and filesystem boundaries.
- defaultSerializeQueryArgs sorts plain-object keys, encodes bigint values, memoizes plain-object arguments in a WeakMap, and returns endpointName(serializedArgs); endpoint serializers may return a string directly or a value for default serialization.
- buildInitiateAnyQuery carries originalArgs, endpointName, queryCacheKey, subscription options, and forceRefetch into the thunk; its returned handle resolves from selected state and exposes abort, unwrap, refetch, unsubscribe, and subscription updates.
- executeRequest validates argSchema when enabled, then calls baseQuery(endpoint.query(arg), api, extraOptions) or endpoint.queryFn; successful data passes rawResponseSchema, transformResponse, and responseSchema in that order.
- fetchBaseQuery prepares headers, serializes JSON-compatible bodies and query parameters, joins the URL, and calls fetchFn with a Request; fetch, timeout, parsing, and HTTP-status failures return distinct error shapes with request/response metadata.
- Pending actions store request IDs, original arguments, and timestamps. Fulfilled writes reject mismatched request IDs unless upserting, then invoke endpoint merge or structural sharing; rejected writes likewise preserve the active request's ownership.
- React useQuery combines subscription and state hooks: argument changes unsubscribe the previous handle and dispatch initiate, while useQueryState derives a memoized endpoint selector and uses shallowEqual for subscription to Redux state.
- Optimistic updateQueryData turns a recipe into patches and inverse patches, exposes undo through patchQueryData, and applies patches to cached data; infinite requests instead accumulate aligned pages/pageParams arrays and trim them with maxPages.
- Rehydration moves application-supplied action payloads into completed query and fixed-key mutation cache entries. Separately, generateEndpoints resolves a schema path/URL, generates and formats TypeScript, then returns text or writes outputFile relative to cwd.
Behavior traces
The following traces follow inspected execution paths through initialization, fetching, editing, authentication, rehydration, and generation. They include cache-hit, failure, and subscription branches that change observable behavior. These are source-derived walkthroughs, not runtime observations.
- API initialization: React createApi calls baseCreateApi, applies defaults, initializes modules, then injectEndpoints evaluates definitions and calls each module's injectEndpoint; core attaches select/initiate and React attaches named hooks.
- Basic startup: index.tsx calls setupStore, which configures the Pokémon reducer and middleware, then renders Provider/App; App calls useGetPokemonByNameQuery('bulbasaur') against the endpoint's Pokémon URL.
- Query initiation: useQuerySubscriptionCommonImpl dispatches initiate; buildInitiateAnyQuery serializes arguments and dispatches queryThunk. Its condition permits upserts first, rejects an in-flight duplicate, honors forcing, and otherwise skips fulfilled cached entries.
- Request completion: executeRequest invokes the endpoint transport and transforms/validates its output; executeEndpoint returns fulfillWithValue, buildSlice writes the cache, and useQueryState selects the result for loading/error/data rendering.
- Post edit: PostDetail calls updatePost({id,name}).unwrap(); mutation pending triggers onQueryStarted, which dispatches updateQueryData('getPost', id), then awaits queryFulfilled and undoes patches on rejection. The UI shows an error toast and exits editing in finally.examples/query/react/optimistic-update/src/features/posts/PostDetail.tsx#L104-L123examples/query/react/optimistic-update/src/app/services/posts.ts#L36-L54packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts#L443-L487packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts#L489-L503
- After a tagged mutation, buildInvalidationByTagsHandler calculates invalidatesTags and queues them while delayed invalidation has pending requests; once processed, matching unobserved queries are removed and subscribed initialized queries dispatch a forced refetch.
- Login: Login awaits login(formState).unwrap(), dispatches setCredentials, and navigates to '/'; prepareHeaders reads auth.token for later requests. PrivateOutlet selects auth.user to render Outlet or redirect, while the mock protected handler checks the bearer header.
- Persistence/generation boundaries: a REHYDRATE extractor supplies API state, completed cache entries are restored, and cache collection schedules retention cleanup. The OpenAPI CLI instead resolves config, changes to its directory, requires it, expands parseConfig, and awaits generateEndpoints for each output.
Testing signals
Tests and CI were inspected, not executed; no passing result or measured coverage is asserted. The inspected suites combine Vitest runtime/type checks, mocked HTTP, React Testing Library, transformation fixtures, and Playwright application checks. Coverage includes consequential failure and concurrency branches, but mock-based assertions have specific limits. This investigation is bounded and does not establish exhaustive repository coverage.
- Toolkit's test script runs vitest --typecheck --run; configuration uses jsdom, globals, source test/spec discovery, and setup that installs node-fetch globals and starts MSW with unhandled requests treated as errors.
- fetchBaseQuery tests assert JSON success, empty-body null, HTTP 500 data, connection-loss FETCH_ERROR, invalid-JSON PARSING_ERROR, and asynchronous bearer-header preparation.
- React hook tests inspect skip and skipToken transitions, including retained data with cleared currentData and removed subscriptions; createApi tests exercise argument schema validation and failure-handler payloads.
- Optimistic tests assert forward/inverse patch contents and hook updates during an in-flight refetch. Infinite-query tests assert unbounded growth, maxPages trimming in both directions, and development-time validation of maxPages/getPreviousPageParam.
- createAsyncThunk tests assert pending-to-rejected behavior after abort, preserved abort reasons, no fulfilled action at resolution of an aborted signal-unaware payload creator handle, and immediate handle resolution while underlying work remains running. The sampled assertions do not wait for that underlying work to finish.
- OpenAPI tests spawn the CLI, compare generated snapshots, check JS/TS/JSON equivalence, filtering, and missing operation IDs; GraphQL adapter tests use mocked clients, and the URL-initialization case only asserts that a function is created.
- Codemod tests use runInlineTest against input/output fixtures; the helper's 'is idempotent' case repeats the original input rather than applying the transform to transformed output, so that assertion does not demonstrate second-pass stability.
- Inspected CI configures artifact-based Toolkit runtime/type testing and detached portability checks, plus a separate OpenAPI artifact workflow. Next's Playwright fixture checks server-entrypoint rendering, counter/async interactions, and query output; these configurations and tests were not executed here.
Risk map
These findings describe source-visible trust boundaries and maintenance hazards, not confirmed vulnerabilities. Network destinations, executable configuration, and generated-file writes deserve explicit ownership in consuming applications. Cache behavior also depends on middleware installation, request completion, and rehydration timing. Test limitations and package-resolution coupling constrain what source inspection alone can establish.
- fetchBaseQuery prepares headers before joining URLs, and joinUrls accepts absolute endpoint URLs unchanged. Applications that attach bearer headers indiscriminately must review endpoint destination control; this is a source-visible trust boundary, not a demonstrated leak.
- The authentication fixture stores user/token in Redux and its mock login returns a token without checking submitted credentials; PrivateOutlet checks user presence. It demonstrates request authentication wiring rather than production credential validation.
- OpenAPI CLI configuration is executable input: optional TypeScript loaders are registered, cwd changes to the config directory, and require(configFile) executes it. Schema bundling accepts HTTP resolution and outputFile is resolved without a repository-root restriction.
- The codemod CLI derives the transform path from argv[2], expands user-supplied globs, and invokes jscodeshift through execaSync with inherited stdio; the inspected invocation supplies no dry-run option.
- API middleware installation is a functional requirement: React hooks probe it and throw a development error when missing, while handler execution requires state at reducerPath and registration tracks API identity conflicts.
- Delayed invalidation is the default and waits while the middleware's pending-request counter is positive. Schema failures without catchSchemaFailure bypass normal tag handling, making request completion and error classification consequential cache-consistency boundaries.
- Persistence documentation warns about stale API data; cache collection explicitly notes that rehydration before endpoint injection uses global retention instead of endpoint-specific keepUnusedDataFor.
- Artifact validation is sensitive to aliases and workspace linking: CI removes source aliases, changes the package name, and detaches portability installs to target the tarball. Separately, codemod second-pass idempotence and real GraphQL transport remain unproven by the inspected specific tests.
Extension points
Customization is organized around factories, endpoint definitions, middleware registration, and reducer injection. RTK Query modules augment a shared API during initialization and endpoint injection. Application-specific lifecycle callbacks and transport implementations sit above the core machinery. Companion tools expose configuration and AST-transform boundaries for extending generated or migrated code.
- buildCreateApi accepts modules implementing init; each initialized module receives injectEndpoint calls. reactHooksModule supports custom React Redux hooks, batching, selector creation, and optional side effects during render.
- injectEndpoints adds query/mutation/infiniteQuery definitions and controls duplicate replacement through overrideExisting; enhanceEndpoints adds tag types or mutates/merges existing endpoint definitions.
- Endpoints can supply queryFn instead of query/baseQuery translation, with access to API context and a baseQuery callback. fetchBaseQuery separately permits custom fetchFn, prepareHeaders, serializers, status validation, and response handlers.
- onQueryStarted receives requestId, getCacheEntry, queryFulfilled, and query-only updateCachedData; middleware resolves or rejects its lifecycle promise from terminal thunk actions.
- combineSlices.inject updates its reducer map and recomposes reducers, refusing conflicting replacements unless overrideExisting is set; slice.injectInto delegates to that injectable interface and returns adjusted selector properties.
- createDynamicMiddleware registers middleware by function identity and caches composition by version; createListenerMiddleware offers startListening/stopListening, while buildCreateSlice can opt into asyncThunkCreator.
- OpenAPI generation supports multiple outputs with shared/per-output options, endpoint and parameter matchers, operationId transformers, query/mutation overrides, explicit tags, hook selection, and alternative enum representations.
- Codemods plug in as transforms/<argv-name>/index.ts; createSliceBuilder exports a tsx parser and Transform. Documentation navigation is another explicit registry: new pages must be listed in docs/sidebars.ts.
Contributor handoff
Begin from the owning package and public entrypoint before following internal builders. Preserve runtime behavior and exported type inference together, especially across cache identity and package-resolution boundaries. Tests and CI were inspected, not executed, so this report provides test-selection guidance rather than validation results. The inventory and investigation are bounded; uninspected files and scenarios remain unknown.
- Read root/package manifests and pnpm-workspace.yaml before selecting commands: pnpm 11.23.0 is pinned, the workspace is selective, hoisted linking is configured, and autoInstallPeers/linkWorkspacePackages are disabled.
- For store changes, inspect configureStore and both default-builder files together; custom enhancer callbacks must retain the middleware enhancer, and invariant middleware is added only outside production.
- For reducer changes, preserve case-before-matcher execution, draft versus primitive handling, and lazy slice reducer construction. The removed object form of extraReducers is rejected outside production.
- For RTK Query fixes, read createApi, core/module, buildInitiate, and buildThunks before changing cache behavior; preserve serializer precedence and the condition order that allows upserts before blocking pending requests.
- For listener changes, keep reducer-before-effect ordering and synchronous getOriginalState semantics; cancellation, child-task joining, and executing-listener tracking require coordinated lifecycle handling.
- When execution is separately authorized, use the owning package's focused Vitest test first, then relevant type tests; Toolkit provides test and type-tests scripts, with type-test discovery configured in tsconfig.test.json. Here these scripts and CI were inspected only.
- Public type or export changes need artifact-level review: declarations include .d.ts/.d.mts variants, CI removes source aliases for tarball testing, and CONTRIBUTING requests updating the API report for external-facing type changes.
- Follow package-specific formatting overrides and edit source rather than emitted bundles. For docs, account for the external website and type-checked MDX; for codegen, distinguish text-return generation from outputFile writes before choosing a verification path.
Languages
| Language | Files | Share of source |
|---|---|---|
| TypeScript | 563 | 94% |
| Markdown | 100 | docs/config |
| JSON | 95 | docs/config |
| JavaScript | 34 | 6% |
| YAML | 23 | docs/config |
| CSS | 17 | docs/config |
| HTML | 11 | docs/config |
| Kotlin | 2 | 0% |
Start reading here
Probable source entrypoint: packages/ — inferred from the directory tree and manifest, not the upstream docs.
Source roots
packages/ (361 files)
Repository structure
| Top-level path | Files |
|---|---|
examples/ | 463 |
packages/ | 361 |
docs/ | 74 |
.github/ | 8 |
_artifacts/ | 3 |
skills/ | 2 |
Docs found: CONTRIBUTING.mddocs/README.mddocs/introduction/getting-started.mddocs/rtk-query/comparison.mddocs/rtk-query/overview.mddocs/usage/immer-reducers.mddocs/usage/usage-guide.mddocs/usage/usage-with-typescript.md
Package
package.json — rtk-monorepo, 20 declared dependencies.
@babel/code-frame@babel/core@babel/generator@babel/helper-compilation-targets@babel/traverse@babel/types@size-limit/webpack@types/react@types/react-domnetlify-plugin-cacheoxfmtoxlint
CI & config entrypoints
examples/type-portability/nodenext-esm/src/App.tsx— React rootexamples/type-portability/nodenext-cjs/src/App.tsx— React rootexamples/type-portability/bundler/src/App.tsx— React rootexamples/query/react/prefetching/src/App.tsx— React rootexamples/query/react/mutations/src/App.tsx— React rootexamples/query/react/basic/src/App.tsx— React rootexamples/query/react/graphql-codegen/src/App.tsx— React rootexamples/query/react/kitchen-sink/src/App.tsx— React rootexamples/query/react/graphql/src/App.tsx— React rootexamples/query/react/infinite-queries/vite.config.ts— Vite config
Structural health signals
Average score 7.3/10 across 96 analyzed source files; 13 hotspots surfaced.
packages/toolkit/src/query/endpointDefinitions.ts— 1703 lines, score 5.2 (Large file, Deep nesting)packages/toolkit/src/query/core/module.ts— 733 lines, score 5.2 (Large file, Deep nesting)packages/toolkit/src/query/core/buildThunks.ts— 1143 lines, score 5.4 (Large file, Deep nesting)
These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.
Recent history
e7a8b318df282026-09-29 — Skip Release Commit workflow in forks (#5458)370f7eb6403b2026-09-28 — Release 2.13.08c40241546d92026-09-28 — Fix release-it commands for PNPM483f0fb5b5c22026-09-28 — Fix unstable selector reference inside of `useQueryState` and `isSuccess` during refetch-after-error (#5456)62103f5409a92026-09-28 — Fix TS7 errors and update TS matrix (#5455)