Skip to content

Releases: reduxjs/redux-toolkit

v2.2.5

16 May 07:04
Compare
Choose a tag to compare

This bugfix release fixes an issue in the recent createEntityAdapter sorting perf improvements that could (in specific cases) cause Immer to throw an error when trying to read a plain JS value instead of a proxy-wrapped value.

What's Changed

  • Fix missed spot where use of current may fail if the value is not a draft by @markerikson in #4412

Full Changelog: v2.2.4...v2.2.5

v2.2.4

09 May 02:02
Compare
Choose a tag to compare

This bugfix release improves sorting performance in createEntityAdapter, shrinks the code size in matcher utilities, fixes assorted issues with query hooks, and makes several TS tweaks.

Changelog

Entity Adapter Sorting Performance

Users reported in #4252 that the sorting performance of createEntityAdapter seemed abnormally bad - the provided comparison functions were being called far more times than expected.

Upon investigation, we had a couple of problems. We were always starting from an array that was in insertion order, not the existing sorted order, and that would always require significant effort to re-sort even if there weren't any actual changes to the sorted results. Also, the sorting checks required frequent access to Immer's Proxy-wrapped values, even in cases where all we needed was the plain state values for comparison purposes.

We've reworked the internal sorting logic to always start from the existing sorted array, do reads against a plain value to avoid the Proxy getter overhead where possible, and optimized inserts into existing sorted arrays. This should significantly speed up sorted entity adapter behavior.

Matcher Code Size Optimization

We've reworked the internals of the thunk-related matchers to deduplicate some of the logic, shaving a few bytes off the final bundle size.

RTK Query Hook Updates

defaultSerializeQueryArgs can now handle BigInt values safely.

The isLoading flag logic was improved to handle errors when a query hook tries to subscribe.

TS Updates

create.asyncThunk's types were improved to avoid cases where it might infer any.

We've made several internal types changes to work correctly with React 19's upcoming types.

The retryCondition method now receives unknown as an argument, instead of always assuming the user is using fetchBaseQuery.

Other Changes

The Reselect dep has been bumped to 5.1.0 to match the expected internal usage of createSelector.withTypes().

What's Changed

Full Changelog: v2.2.3...v2.2.4

v2.2.3

31 Mar 20:42
Compare
Choose a tag to compare

This bugfix release fixes the types for functions that accept a React Context instance to match the changes in React Redux v9.

What's Changed

  • Update React Redux dependency to v9, and update docs to use .withTypes by @aryaemami59 in #4308

Full Changelog: v2.2.2...v2.2.3

v2.2.2

21 Mar 00:22
Compare
Choose a tag to compare

This patch release fixes an incorrect build setting for the legacy-esm artifacts, and fixes an issue with RTKQ query hooks didn't always remove the cache entries if arguments were changed rapidly.

Changes

legacy-esm Artifact Transpilation

The legacy-esm build artifacts are intended for use by Webpack 4. Those were supposed to be transpiled to target "es2017", but were in fact still set to target "esnext" - an oversight during the 2.0 development cycle. This release fixes that setting, so those artifacts are now correctly transpiled.

Other Fixes

RTKQ query hooks now handle additional actions around argument changes that should result in cache entries being removed.

Additionally, 2.2.1 contained a fix to an incorrectly named type: TypedUseMutationTrigger is now TypedMutationTrigger.

What's Changed

  • rename TypedUseMutationTrigger to TypedMutationTrigger, and add deprecated alias by @EskiMojo14 in #4204
  • Fixed memory leak in rapid hook arg changing by @riqts in #4268
  • Fix incorrect legacy-esm target by @markerikson in #4284

Full Changelog: v2.2.0...v2.2.2

v2.2.0

12 Feb 21:45
Compare
Choose a tag to compare

This minor release:

  • Adds a second parameter to entityAdapter.getInitialState(additionalProps, entities) to allow prefilling state
    • Equivalent to entityAdapter.setAll(entityAdapter.getInitialState(additionalProps), entities)
    • First parameter can be undefined if no additional properties are desired
  • Allows initialising combineSlices with no static reducers
    • Previously const combinedReducer = combineSlices().withLazyLoadedSlices<LazyLoadedSlices>() would have thrown an error
    • Now returns a "no-op" reducer that just returns an empty object until first reducer injected
  • Allows a new 'throw' value for overrideExisting in injectEndpoints, which throws an error if a definition is injected with a name which is already used
  • Exports more type helpers for RTKQ hook and trigger types
  • Exports types related to overriding result types in enhanceEndpoints
  • Fixes state inference for injected slices when undeclared (i.e. not in LazyLoadedSlices)
  • Adds a action.meta.arg.isPrefetch value to query thunk actions when prefetched

What's Changed

New Contributors

Full Changelog: v2.1.0...v2.2.0

v2.1.0

24 Jan 10:28
Compare
Choose a tag to compare

This minor release:

  • adds withTypes methods to listenerMiddleware and createDraftSafeSelector
  • adds a skipPollingIfUnfocused option to RTK Query
  • adds the ability to customise the createSelector instance used by RTK Query
  • reworks slice selector logic to avoid depending on this value
  • fixes the order and inference of create.asyncThunk type parameters
  • fixes requirements for meta fields returned from queryFns
  • marks promises that will never reject as safe, in preparation for typescript-eslint/typescript-eslint#7008

What's Changed

New Contributors

Full Changelog: v2.0.1...v2.1.0

v2.0.0

04 Dec 14:10
Compare
Choose a tag to compare

This major release :

  • Removes the deprecated object syntax from createSlice and createReducer
  • Removes other deprecated options
  • Updates the middleware and enhancers options of configureStore to require callbacks
  • Updates the packaging for better ESM/CJS compatibility and modernizes the build output
  • Includes all changes to Redux core 5.0, Reselect 5.0, and Redux Thunk 3.0
  • Updates RTKQ default subscription behavior
  • Adds a new combineSlices method with support for lazy-loading slice reducers
  • Adds a new "dynamic middleware" middleware with support for adding middleware at runtime
  • Adds a new callback syntax to createSlice.reducers, with optional support for defining thunks inside of createSlice
  • Adds the autoBatchEnhancer to configureStore by default
  • Has many additional TS tweaks and improvements

This release has breaking changes. (Note: v2.0.1 was released with a couple hotfixes for Reselect and Redux Thunk right as this was being finalized.)

This release is part of a wave of major versions of all the Redux packages: Redux Toolkit 2.0, Redux core 5.0, React-Redux 9.0, Reselect 5.0, and Redux Thunk 3.0.

For full details on all of the breaking changes and other significant changes to all of those packages, see the "Migrating to RTK 2.0 and Redux 5.0" migration guide in the Redux docs.

Note

The Redux core, Reselect, and Redux Thunk packages are included as part of Redux Toolkit, and RTK users do not need to manually upgrade them - you'll get them as part of the upgrade to RTK 2.0. (If you're not using Redux Toolkit yet, please start migrating your existing legacy Redux code to use Redux Toolkit today!)

# RTK
npm install @reduxjs/toolkit
yarn add @reduxjs/toolkit

Changelog

Object syntax for createSlice.extraReducers and createReducer removed

RTK's createReducer API was originally designed to accept a lookup table of action type strings to case reducers, like { "ADD_TODO": (state, action) => {} }. We later added the "builder callback" form to allow more flexibility in adding "matchers" and a default handler, and did the same for createSlice.extraReducers.

We have removed the "object" form for both createReducer and createSlice.extraReducers in RTK 2.0, as the builder callback form is effectively the same number of lines of code, and works much better with TypeScript.

As an example, this:

const todoAdded = createAction('todos/todoAdded')

createReducer(initialState, {
  [todoAdded]: (state, action) => {},
})

createSlice({
  name,
  initialState,
  reducers: {
    /* case reducers here */
  },
  extraReducers: {
    [todoAdded]: (state, action) => {},
  },
})

should be migrated to:

createReducer(initialState, (builder) => {
  builder.addCase(todoAdded, (state, action) => {})
})

createSlice({
  name,
  initialState,
  reducers: {
    /* case reducers here */
  },
  extraReducers: (builder) => {
    builder.addCase(todoAdded, (state, action) => {})
  },
})
Codemods

To simplify upgrading codebases, we've published a set of codemods that will automatically transform the deprecated "object" syntax into the equivalent "builder" syntax.

The codemods package is available on NPM as @reduxjs/rtk-codemods. More details are available here.

To run the codemods against your codebase, run npx @reduxjs/rtk-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js.

Examples:

npx @reduxjs/rtk-codemods createReducerBuilder ./src

npx @reduxjs/rtk-codemods createSliceBuilder ./packages/my-app/**/*.ts

We also recommend re-running Prettier on the codebase before committing the changes.

These codemods should work, but we would greatly appreciate feedback from more real-world codebases!

configureStore Options Changes

configureStore.middleware must be a callback

Since the beginning, configureStore has accepted a direct array value as the middleware option. However, providing an array directly prevents configureStore from calling getDefaultMiddleware(). So, middleware: [myMiddleware] means there is no thunk middleware added (or any of the dev-mode checks).

This is a footgun, and we've had numerous users accidentally do this and cause their apps to fail because the default middleware never got configured.

As a result, we've now made the middleware only accept the callback form. If for some reason you still want to replace all of the built-in middleware, do so by returning an array from the callback:

const store = configureStore({
  reducer,
  middleware: (getDefaultMiddleware) => {
    // WARNING: this means that _none_ of the default middleware are added!
    return [myMiddleware]
    // or for TS users, use:
    // return new Tuple(myMiddleware)
  },
})

But note that we consistently recommend not replacing the default middleware entirely, and that you should use return getDefaultMiddleware().concat(myMiddleware).

configureStore.enhancers must be a callback

Similarly to configureStore.middleware, the enhancers field must also be a callback, for the same reasons.

The callback will receive a getDefaultEnhancers function that can be used to customise the batching enhancer that's now included by default.

For example:

const store = configureStore({
  reducer,
  enhancers: (getDefaultEnhancers) => {
    return getDefaultEnhancers({
      autoBatch: { type: 'tick' },
    }).concat(myEnhancer)
  },
})

It's important to note that the result of getDefaultEnhancers will also contain the middleware enhancer created with any configured/default middleware. To help prevent mistakes, configureStore will log an error to console if middleware was provided and the middleware enhancer wasn't included in the callback result.

const store = configureStore({
  reducer,
  enhancers: (getDefaultEnhancers) => {
    return [myEnhancer] // we've lost the  middleware here
    // instead:
    return getDefaultEnhancers().concat(myEnhancer)
  },
})

Also, note that if you supply the enhancers field, it must come after the middleware field in order for TS inference to work properly.

Standalone getDefaultMiddleware and getType removed

The standalone version of getDefaultMiddleware has been deprecated since v1.6.1, and has now been removed. Use the function passed to the middleware callback instead, which has the correct types.

We have also removed the getType export, which was used to extract a type string from action creators made with createAction. Instead, use the static property actionCreator.type.

RTK Query behaviour changes

We've had a number of reports where RTK Query had issues around usage of dispatch(endpoint.initiate(arg, {subscription: false})). There were also reports that multiple triggered lazy queries were resolving the promises at the wrong time. Both of these had the same underlying issue, which was that RTKQ wasn't tracking cache entries in these cases (intentionally). We've reworked the logic to always track cache entries (and remove them as needed), which should resolve those behavior issues.

We also have had issues raised about trying to run multiple mutations in a row and how tag invalidation behaves. RTKQ now has internal logic to delay tag invalidation briefly, to allow multiple invalidations to get handled together. This is controlled by a new invalidationBehavior: 'immediate' | 'delayed' flag on createApi. The new default behavior is 'delayed'. Set it to 'immediate' to revert to the behavior in RTK 1.9.

In RTK 1.9, we reworked RTK Query's internals to keep most of the subscription status inside the RTKQ middleware. The values are still synced to the Redux store state, but this is primarily for display by the Redux DevTools "RTK Query" panel. Related to the cache entry changes above, we've optimized how often those values get synced to the Redux state for perf.

ESM/CJS Package Compatibility

The biggest theme of the Redux v5 and RTK 2.0 releases is trying to get "true" ESM package publishing compatibility in place, while still supporting CJS in the published package.

The primary build artifact is now an ESM file, dist/redux-toolkit.modern.mjs. Most build tools should pick this up. There's also a CJS artifact, and a second copy of the ESM file named redux-toolkit.legacy-esm.js to support Webpack 4 (which does not recognize the exports field in package.json). Additionally, all of the build artifacts now live under ./dist/ in the published package.

Modernized Build Output

We now publish modern JS syntax targeting ES2020, including optional chaining, object spread, and other modern syntax. If you need to target older browsers, please transpile the packages yourself (or use the legacy-esm build artifact for ES2017).

Build Tooling

We're now building the package using https://github.com/egoist/tsup. We also now include sourcemaps for the ESM and CJS artifacts.

Dropping UMD Builds

Redux has always shipped with UMD build artifacts. These are primarily meant for direct import as script tags, such as in a CodePen or a no-bundler build environment.

We've dropped those build artifacts from the published package, on the grounds that the use cases seem pretty rare today.

There's now a `redux-toolkit.browser.mj...

Read more

v2.0.0-rc.3

02 Dec 04:20
Compare
Choose a tag to compare
v2.0.0-rc.3 Pre-release
Pre-release

This release candidate updates to the latest Reselect 5.0 RC to pick up the rename of defaultMemoize to lruMemoize.

Note that we hope to release Redux Toolkit 2.0, Redux core 5.0, and React-Redux 9.0 by this weekend!

See the preview Redux Toolkit 2.0 + Redux core 5.0 Migration Guide for an overview of breaking changes in RTK 2.0 and Redux core.

The 2.0 integration branch contains the docs preview for the 2.0 changes. Not all changes are documented yet, but you can see API reference pages for most of the new features here:

npm install @reduxjs/toolkit@next

yarn add @reduxjs/toolkit@next

Changelog

RTK Query Selector Usage Fixes

The previous v2.0.0-rc.2 release picked up Reselect's dev mode checks for result functions that just return their input, like x => x. Turns out that some of RTK Query's internal selector usage did that in some cases :) That resulted in a ton of warnings being printed. We've updated our internals to fix that.

Reselect Changes

The Reselect defaultMemoize function has now been renamed to lruMemoize, since it's no longer the default. See the Reselect v5.0.0-rc.1 release notes for more details.

What's Changed

Full Changelog: v2.0.0-rc.2...v2.0.0-rc.3

v2.0.0-rc.2

01 Dec 05:02
Compare
Choose a tag to compare
v2.0.0-rc.2 Pre-release
Pre-release

This release candidate updates to the latest Reselect 5.0 RC to pick up the change to use weakMapMemoize as the default inside createSelector.

Note that we hope to release Redux Toolkit 2.0, Redux core 5.0, and React-Redux 9.0 by the start of December! (If we don't hit that, we'll aim for January, after the holidays.)

See the preview Redux Toolkit 2.0 + Redux core 5.0 Migration Guide for an overview of breaking changes in RTK 2.0 and Redux core.

The 2.0 integration branch contains the docs preview for the 2.0 changes. Not all changes are documented yet, but you can see API reference pages for most of the new features here:

npm install @reduxjs/toolkit@next

yarn add @reduxjs/toolkit@next

Changelog

Reselect Changes

Reselect v5.0.0-rc.0 makes the breaking change to use weakMapMemoize as the default memoization implementation for createSelector. This memoizer has an effectively infinite cache size, which should cut down on the number of recalculations in a typical app, and help improve performance overall. This is a breaking change, but one that should be invisible to most users.

It also adds a new dev-mode check for result functions that look like x => x, which is almost always a mistake.

See the Reselect v5.0.0-rc.0 release notes for more details.

What's Changed

  • Bump Reselect to 5.0.0-rc.0 to pick up weakMapMemoize change by @markerikson in #3928

Full Changelog: v2.0.0-rc.1...v2.0.0-rc.2

v2.0.0-rc.1

24 Nov 17:05
Compare
Choose a tag to compare
v2.0.0-rc.1 Pre-release
Pre-release

This release candidate updates to the latest Redux 5.0 RC to use its exported isAction and isPlainObject util methods, renames the pre-minified ESM production build to redux-toolkit.browser.mjs and drops the ESM precompiled dev build, and updates build tooling.

Note that we hope to release Redux Toolkit 2.0, Redux core 5.0, and React-Redux 9.0 by the start of December! (If we don't hit that, we'll aim for January, after the holidays.)

See the preview Redux Toolkit 2.0 + Redux core 5.0 Migration Guide for an overview of breaking changes in RTK 2.0 and Redux core.

The 2.0 integration branch contains the docs preview for the 2.0 changes. Not all changes are documented yet, but you can see API reference pages for most of the new features here:

npm install @reduxjs/toolkit@next

yarn add @reduxjs/toolkit@next

Changelog

isAction Predicate

We recently added an isAction predicate to RTK, then realized it's better suited for the Redux core. This can be used anywhere you have a value that could be a Redux action object, and you need to check if it is actually an action. This is specifically useful for use with the updated Redux middleware TS types, where the default value is now unknown and you need to use a type guard to tell TS that the current value is actually an action.

This is now exported from the Redux core, and re-exported from RTK, which also uses it internally to avoid duplicating that logic.

We've also exported the isPlainObject util that's been in the Redux codebase for years as well.

ESM Build Artifacts

We previously dropped the UMD build artifacts in an earlier alpha, but added ESM build artifacts that are pre-compiled to remove the process.env.NODE_ENV definitions, with the intent that these are useable as <script type="module"> tags in the browser. Those were previously named as redux-toolkit.modern.development.mjs and redux-toolkit.modern.production.mjs.

We've renamed the production artifact to redux-toolkit.browser.mjs to be consistent with the other Redux-related packages, and removed the dev build artifact on the grounds that we don't think there's enough likely usage to include it. If you think you would specifically benefit from having an ESM browser-compatible dev artifact, let us know!

What's Changed

Full Changelog: v2.0.0-rc.0...v2.0.0-rc.1