Releases: reduxjs/redux-toolkit
v2.0.0-alpha.6
This is an alpha release for Redux Toolkit 2.0, and has breaking changes. This release updates createSlice
to allow declaring thunks directly inside the reducers
field using a callback syntax, adds a new "dynamic middleware" middleware, updates configureStore
to add the autoBatchEnhancer
by default, removes the .toString()
override from action creators, updates Reselect from v4.x to v5.0-alpha, updates the Redux core to v5.0-alpha.6, and includes the latest changes from 1.9.x.
npm i @reduxjs/toolkit@alpha
yarn add @reduxjs/toolkit@alpha
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 some of the new features here:
Changelog
Declaring Thunks Inside createSlice.reducers
One of the oldest feature requests we've had is the ability to declare thunks directly inside of createSlice
. Until now, you've always had to declare them separately, give the thunk a string action prefix, and handle the actions via createSlice.extraReducers
:
// Declare the thunk separately
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId: number, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
const usersSlice = createSlice({
name: 'users',
initialState,
reducers: {
// standard reducer logic, with auto-generated action types per reducer
},
extraReducers: (builder) => {
// Add reducers for additional action types here, and handle loading state as needed
builder.addCase(fetchUserById.fulfilled, (state, action) => {
state.entities.push(action.payload)
})
},
})
Many users have told us that this separation feels awkward.
We've wanted to include a way to define thunks directly inside of createSlice
, and have played around with various prototypes. There were always two major blocking issues, and a secondary concern:
1 It wasn't clear what the syntax for declaring a thunk inside should look like.
2. Thunks have access to getState
and dispatch
, but the RootState
and AppDispatch
types are normally inferred from the store, which in turn infers it from the slice state types. Declaring thunks inside createSlice
would cause circular type inference errors, as the store needs the slice types but the slice needs the store types. We weren't willing to ship an API that would work okay for our JS users but not for our TS users, especially since we want people to use TS with RTK.
3. You can't do synchronous conditional imports in ES modules, and there's no good way to make the createAsyncThunk
import optional. Either createSlice
always depends on it (and adds that to the bundle size), or it can't use createAsyncThunk
at all.
We've settled on these compromises:
- You can declare thunks inside of
createSlice.reducers
, by using a "creator callback" syntax for thereducers
field that is similar to thebuild
callback syntax in RTK Query'screateApi
(using typed functions to create fields in an object). Doing this does look a bit different than the existing "object" syntax for thereducers
field, but is still fairly similar. - You can customize some of the types for thunks inside of
createSlice
, but you cannot customize thestate
ordispatch
types. If those are needed, you can manually do anas
cast, likegetState() as RootState
. createSlice
does now always depend oncreateAsyncThunk
, so thecreateAsyncThunk
implementation will get added to the bundle.
In practice, we hope these are reasonable tradeoffs. Creating thunks inside of createSlice
has been widely asked for, so we think it's an API that will see usage. If the TS customization options are a limitation, you can still declare thunks outside of createSlice
as always, and most async thunks don't need dispatch
or getState
- they just fetch data and return. And finally, createAsyncThunk
is already being used in many apps, either directly or as part of RTK Query, so in that case there's no additional bundle size increase - you've already paid that cost.
Here's what the new callback syntax looks like:
const todosSlice = createSlice({
name: 'todos',
initialState: {
loading: false,
todos: [],
} as TodoState,
reducers: (create) => ({
// A normal "case reducer", same as always
deleteTodo: create.reducer((state, action: PayloadAction<number>) => {
state.todos.splice(action.payload, 1)
}),
// A case reducer with a "prepare callback" to customize the action
addTodo: create.preparedReducer(
(text: string) => {
const id = nanoid()
return { payload: { id, text } }
},
// action type is inferred from prepare callback
(state, action) => {
state.todos.push(action.payload)
}
),
// An async thunk
fetchTodo: create.asyncThunk(
// Async payload function as the first argument
async (id: string, thunkApi) => {
const res = await fetch(`myApi/todos?id=${id}`)
return (await res.json()) as Item
},
// An object containing `{pending?, rejected?, fulfilled?, options?}` second
{
pending: (state) => {
state.loading = true
},
rejected: (state, action) => {
state.loading = false
},
fulfilled: (state, action) => {
state.loading = false
state.todos.push(action.payload)
},
}
),
}),
})
// `addTodo` and `deleteTodo` are normal action creators.
// `fetchTodo` is the async thunk
export const { addTodo, deleteTodo, fetchTodo } = todosSlice.actions
"Dynamic Middleware" Middleware
A Redux store's middleware pipeline is fixed at store creation time and can't be changed later. We have seen ecosystem libraries that tried to allow dynamically adding and removing middleware, potentially useful for things like code splitting.
This is a relatively niche use case, but we've built our own version of a "dynamic middleware" middleware. Add it to the Redux store at setup time, and it lets you add and remove middleware later at runtime. It also comes with a React hook integration that will automatically add a middleware to the store and return the updated dispatch
method.
import { createDynamicMiddleware, configureStore } from '@reduxjs/toolkit'
const dynamicMiddleware = createDynamicMiddleware()
const store = configureStore({
reducer: {
todos: todosReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().prepend(dynamicMiddleware.middleware),
})
// later
dynamicMiddleware.addMiddleware(someOtherMiddleware)
Store Adds autoBatchEnhancer
By Default
In v1.9.0, we added a new autoBatchEnhancer
that delays notifying subscribers briefly when multiple "low-priority" actions are dispatched in a row. This improves perf, as UI updates are typically the most expensive part of the update process. RTK Query marks most of its own internal actions as "low-pri" by default, but you have to have the autoBatchEnhancer
added to the store to benefit from that.
We've updated configureStore
to add the autoBatchEnhancer
to the store setup by default, so that users can benefit from the improved perf without needing to manually tweak the store config themselves.
configureStore
now also accepts a callback for the enhancers
option that receives a getDefaultEnhancers()
param, equivalent to how the middleware
callback receives getDefaultMiddleware()
:
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(loggerMiddleware),
preloadedState,
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers().concat(anotherEnhancer),
})
Deprecation Removals
When we first released the early alphas of RTK, one of the main selling points was that you could reuse RTK's action creators as "computed key" fields in the object argument to createReducer
, like:
const todoAdded = createAction("todos/todoAdded");
const reducer = createReducer([], {
[todoAdded]: (state, action) => {}
})
This was possible because createAction
overrides the fn.toString()
field on these action creators to return the action type string. When JS sees the function, it implicitly calls todoAdded.toString()
, which returns "todos/todoAdded"
, and that string is used as the key.
While this capability was useful early on, it's not useful today. Most users never call createAction
, because createSlice
automatically generates action creators. Additionally, it has no TS type safety. TS only sees that the key is a string
, and has no idea what the correct TS type for action
is. We later created the "builder callback" syntax for both createReducer
and createSlice.extraReducers
, started teaching that as the default, and removed the "object" argument to both of those in an earlier RTK 2.0 alpha.
Because of this, we've now removed the fn.toString()
override. If you need to access the type string from an action creator function, those still have a .type
field attached:
const todoAdded = createAction("todos/todoAdded");
console.log(todoAdded.type) // "todos/todoAdded"
We've also removed the standalone export of getDefaultMiddleware
, which has been deprecated ever since we added the callback for the `configureStore.middlewa...
v2.0.0-alpha.5
This is an alpha release for Redux Toolkit 2.0. This release adds a new combineSlices
API for reducer injection, has many changes to our build setup and published package contents, updates the redux
dep to the latest alpha, updates the immer
dep to 10.0 final, includes the latest changes from 1.9.x, and has breaking changes.
Changelog
New combineSlices
API
The Redux core has always included combineReducers
, which takes an object full of "slice reducer" functions and generates a reducer that calls those slice reducers. RTK's createSlice
generates slice reducers + associated action creators, and we've taught the pattern of exporting individual action creators as named exports and the slice reducer as a default export. Meanwhile, we've never had official support for lazy-loading reducers, although we've had sample code for some "reducer injection" patterns in our docs.
This release includes a new combineSlices
API that is designed to enable lazy-loading of reducers at runtime. It accepts individual slices or an object full of slices as arguments, and automatically calls combineReducers
using the sliceObject.name
field as the key for each state field. The generated reducer function has an additional .inject()
method attached that can be used to dynamically inject additional slices at runtime. It also includes a .withLazyLoadedSlices()
method that can be used to generate TS types for reducers that will be added later. See #2776 for the original discussion around this idea.
For now, we are not building this into configureStore
, so you'll need to call const rootReducer = combineSlices(.....)
yourself and pass that to configureStore({reducer: rootReducer})
.
We don't have documentation added for these features yet, but here's example usages from the combineSlices
PR tests:
Basic usage: a mixture of slices and standalone reducers passed to combineSlices
const stringSlice = createSlice({
name: 'string',
initialState: '',
reducers: {},
})
const numberSlice = createSlice({
name: 'number',
initialState: 0,
reducers: {},
})
const booleanReducer = createReducer(false, () => {})
const api = createApi(/* */)
const combinedReducer = combineSlices(
stringSlice,
{
num: numberSlice.reducer,
boolean: booleanReducer,
},
api
)
expect(combinedReducer(undefined, dummyAction())).toEqual({
string: stringSlice.getInitialState(),
num: numberSlice.getInitialState(),
boolean: booleanReducer.getInitialState(),
api: api.reducer.getInitialState(),
})
Basic slice reducer injection
// Create a reducer with a TS type that knows `numberSlice` will be injected
const combinedReducer =
combineSlices(stringSlice).withLazyLoadedSlices<
WithSlice<typeof numberSlice>
>()
// `state.number` doesn't exist initially
expect(combinedReducer(undefined, dummyAction()).number).toBe(undefined)
// Create a new reducer with `numberSlice` injected
const injectedReducer = combinedReducer.inject(numberSlice)
// `state.number` now exists
expect(injectedReducer(undefined, dummyAction()).number).toBe(
numberSlice.getInitialState()
)
Selectors support in createSlice
The existing createSlice
API now has support for defining selectors
directly as part of the slice. By default, these will be generated with the assumption that the slice is mounted in the root state using slice.name
as the field, such as name: "todos"
-> rootState.todos
. You can call sliceObject.getSelectors(selectSliceState)
to generate the selectors with an alternate location, similar to how entityAdapter.getSelectors()
works.
Slice selectors
const slice = createSlice({
name: 'counter',
initialState: 42,
reducers: {},
selectors: {
selectSlice: (state) => state,
selectMultiple: (state, multiplier: number) => state * multiplier,
},
})
// Basic usage
const testState = {
[slice.name]: slice.getInitialState(),
}
const { selectSlice, selectMultiple } = slice.selectors
expect(selectSlice(testState)).toBe(slice.getInitialState())
expect(selectMultiple(testState, 2)).toBe(slice.getInitialState() * 2)
// Usage with the slice reducer mounted under a different key
const customState = {
number: slice.getInitialState(),
}
const { selectSlice, selectMultiple } = slice.getSelectors(
(state: typeof customState) => state.number
)
expect(selectSlice(customState)).toBe(slice.getInitialState())
expect(selectMultiple(customState, 2)).toBe(slice.getInitialState() * 2)
Build Setup Updates
We've switched our build setup to use tsup
, an ESBuild-powered build framework. This release should have identical build artifacts to 2.0.0-alpha.4
, but let us know if there are any issues!
Immer 10.0
Immer 10.0 is now final, and has several major improvements and updates:
- Much faster update perf
- Much smaller bundle size
- Better ESM/CJS package formatting
- No default export
- No ES5 fallback
We've updated RTK to depend on the final Immer 10.0 release .
Redux 5.0 alpha and TS types updates
We've updated RTK to use the latest Redux 5.0-alpha.5
release, which tweaks the Reducer
type, drops the internal $CombinedState
type, and updates middleware types to default to unknown
for actions.
For RTK, we've improved type inference for store enhancers, especially those that add additional fields to the state or store.
What's Changed
- Switch build setup from a custom ESBuild+TS script to
tsup
by @markerikson in #3362 - Use original instead of immer draft for perf by @GeorchW in #3270
- enable enhanceEndpoints.transformResponse to override ResultType by @dmitrigrabov in #2953
- Fix global
responseHandler
being used infetchBaseQuery
by @praxxis in #3137 - reset internalState.currentSubscriptions on
resetApiState
by @phryneas in #3333 - Bump deps and mark
subscriptionUpdated
as autobatched by @markerikson in #3364 - Redux 5alpha5 by @EskiMojo14 in #3367
- add isAction helper function, and ensure listener middleware only runs for actions by @EskiMojo14 in #3372
- Allow inference of enhancer state extensions, and fix inference when using callback form by @EskiMojo14 in #3207
- combineSlices implementation by @EskiMojo14 in #3297
- Merge 1.9.4/5 into v2.0-integration by @markerikson in #3375
- Bump Immer to 10.0 final by @markerikson in #3376
- Allow partial preloaded state for combined slice reducer and update devDeps by @markerikson in #3381
Full Changelog: v2.0.0-alpha.4...v2.0.0-alpha.5
v1.9.5
This bugfix release includes notable improvements to TS type inference when using the enhancers
option in configureStore
, and updates the listener middleware to only check predicates if the dispatched value is truly an action object.
What's Changed
- update to latest remark-typescript-tools by @EskiMojo14 in #3311
- add isAction helper function, and ensure listener middleware only runs for actions by @EskiMojo14 in #3372
- Allow inference of enhancer state extensions, and fix inference when using callback form by @EskiMojo14 in #3207
Full Changelog: v1.9.4...v1.9.5
v1.9.4
This bugfix release includes tweaks to RTKQ options handling, tweaks for perf updates, dependency updates, and updates to our CI tooling.
Also, please check out our ongoing RTK 2.0 alpha releases! They have significant improvements to bundle size, ESM/CJS compatibility, TS typings, and reducer update performance. We're looking for real-world feedback on behavior, performance, and any issues you might run into.
Changelog
RTK Query Options Updates
Passing transformResponse
as part of enhanceEndpoints
can now override the TS type of the original data.
fetchBaseQuery
now properly checks for a global responseHandler
option.
Performance and Internals
RTK Query now uses Immer's original()
to do comparisons inside of copyWithStructuralSharing
, which should significantly speed up performance when applying changes from re-fetched data.
RTKQ's internal subscriptionUpdated
action is now marked as batchable.
We've updated dependencies to Immer 9.0.21, Reselect 4.1.8, and Redux 4.2.1.
CI Updates
We've added a suite of example apps built with different frameworks such as CRA 4, CRA 5, Next, and Vite, as well as examples that check for compatibility in Node with CJS and ESM modes and with various TS module resolution modes.
What's Changed
- Test published artifacts in CI by @markerikson in #3213
- Use Git revision in version and add Node CI examples by @markerikson in #3258
- Add
arethetypeswrong
automated CLI check by @markerikson in #3294 - Add
attw
CLI option to treat problems as non-errors by @markerikson in #3316 - Use original instead of immer draft for perf by @GeorchW in #3270
- enable enhanceEndpoints.transformResponse to override ResultType by @dmitrigrabov in #2953
- Fix global
responseHandler
being used infetchBaseQuery
by @praxxis in #3137 - reset internalState.currentSubscriptions on
resetApiState
by @phryneas in #3333 - Bump deps and mark
subscriptionUpdated
as autobatched by @markerikson in #3364
Full Changelog: v1.9.3...v1.9.4
v2.0.0-alpha.4
This is an alpha release for Redux Toolkit 2.0. This release has many changes to our build setup and published package contents, updates the redux
and redux-thunk
deps to the latest alphas, updates the immer
dep to the latest 10.x beta, and has breaking changes.
npm i @reduxjs/toolkit@alpha
yarn add @reduxjs/toolkit@alpha
Also see the [email protected]
release notes.
Changelog
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.
Earlier alphas made changes to the package.json
contents and published build artifacts in an attempt to get ESM+CJS compat working correctly, but those alphas had several varying compat issues.
We've set up a battery of example applications in the RTK repo that use a variety of build tools (currently CRA4, CRA5, Next 13, and Vite, Node CJS mode, and Node ESM mode), to verify that Redux and Redux Toolkit compile, import, and run correctly with both TS and various bundlers. We've also set up a check using a custom CLI wrapper around https://arethetypeswrong.github.io to check for potential packaging incompatibilities.
This release changes the names and contents of the published build artifacts, and the various exports/module/main
fields in package.json
to point to those.
We already tried to point to ESM build artifacts as the default. That should hopefully be be more consistent now.
As of this release, we think we have ESM+CJS compat working correctly, but we ask that the community try out the alphas in your apps and let us know of any compat problems!
Note: The one known potential issue is that TypeScript's new
moduleResolution: "node16"
mode may see a mismatch between the ESM artifacts and the TS typedefs when imported in a Node CJS environment, and [that may allow hypothetically-incorrect import usage. (See ongoing discussion in https://github.com/arethetypeswrong/arethetypeswrong.github.io/issues/21 .) In practice, we think that probably won't be a concern, and we'll do further investigation before a final release.
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.
For now, we're dropping those build artifacts from the published package, on the grounds that the use cases seem pretty rare today.
We do have browser-ready ESM build artifacts included, which already have process.env.NODE_ENV
compiled away for either development or production behavior. These can be loaded via a script tag that points to that file on Unpkg.
If you have strong use cases for us continuing to include UMD build artifacts, please let us know!
Immer 10 Beta
Immer 10 is now in beta. It has several major changes, including faster perf, dropping ES5 environment support, and switching from a default export to only named exports.
We've updated RTK to depend on [email protected]
.
Performance testing in an artificial RTKQ stress test project showed significant perf increases when dealing with many RTKQ-connected components loading, and that was directly due to Immer-powered reducers executing much faster.
While reducers are not usually the bottleneck in React+Redux apps, this looks like it will be a very nice improvement!
What's Changed
- Fix lint problems and enable linting on CI by @thorn0 in #2992
- Allow TS isolatedModules flag to be set for safer transpilation by @matmannion in #2911
- Test published artifacts in CI by @markerikson in #3213
- Use Git revision in version and add Node CI examples by @markerikson in #3258
- Add
arethetypeswrong
automated CLI check by @markerikson in #3294 - remove "alternative" from descriptions of builder callback by @EskiMojo14 in #3296
- update tip regarding overrideExisting to match actual behaviour by @EskiMojo14 in #3305
- Add
attw
CLI option to treat problems as non-errors by @markerikson in #3316 - Rework build setup and hopefully fix ESM compat issues by @markerikson in #3318
- Bump Immer to 10.0-beta by @markerikson in #3320
Full Changelog: v2.0.0-alpha.2...v2.0.0-alpha.4
v1.9.3
This release fixes a couple issues with the skip/skipToken
options for query hooks, and makes a small perf tweak to serializing query args.
Changelog
Skip Behavior
We made a change in v1.9.0 that tried to make some skip behavior more consistent, including clearing out the cached data. However, we had overlooked that our own docs actually said "skipping a query will keep the cached data", and several users pointed this out as they'd been relying on that behavior.
We've reverted that change. Now, setting {skip: true}
or skipToken
for a query with existing results will keep the data
value (reflecting the last successful query), but currentData
will be undefined (reflecting the current settings).
We also identified and fixed an issue that could cause subscription entries to leak under a specific combination of timing and settings changes.
Query Arg Serialization Perf
RTKQ relies on serializing query arguments to serve as the cache keys, with the default using JSON.stringify()
+ some logic for sorting keys. There was a report that in some apps, large query arg objects could take a while to stringify and this was being done repeatedly. We've added a WeakMap
-based cache for query args to avoid re-serializing existing arg values.
What's Changed
- Revert "clear data on skip" back to its original behavior by @markerikson in #3188
- Use a WeakMap cache for query arg serialization for perf by @markerikson in #3193
Full Changelog: v1.9.2...v1.9.3
v2.0.0-alpha.2
This alpha release updates the Redux core package dependency to 5.0.0-alpha.2
. This release may have breaking changes.
Changelog
Redux v5 Dependency Update
We've updated the redux
dependency from 4.2.x to [email protected]
. The Redux v5 branch contains the TS conversion work we did in 2019, a migration to full ESM package compatibility, and some additional types changes and internal tweaks.
In practice, these hopefully shouldn't affect most codebases, but that's why these are major versions and we're publishing these alphas :)
We'd like users to try out these alphas releases in your apps and let us know of any build/typing/runtime errors or compatibility problems!
Please see the Redux v5 alpha release notes for further details:
- https://github.com/reduxjs/redux/releases/tag/v5.0.0-alpha.0
- https://github.com/reduxjs/redux/releases/tag/v5.0.0-alpha.1
- https://github.com/reduxjs/redux/releases/tag/v5.0.0-alpha.2
What's Changed
- Fix type errors after upgrading to Redux 5 alpha by @Methuselah96 in #3177
- Bump Redux dep to 5.0.0-alpha.2 by @markerikson in #3170
Full Changelog: v2.0.0-alpha.1...v2.0.0-alpha.2
v1.9.2
This bugfix release fixes a memory leak in createListenerMiddleware
, optimizes performance inside serializableMiddleware
, adds new options for fetchBaseQuery
, adds support for path RegExp
exclusions in serializableMiddleware
and immutabilityMiddleware
, and improves some TS types.
Changelog
Bug Fixes
createListenerMiddleware
had a memory leak that turned out to be due to use of Promise.race()
. We've restructured the logic to fix that.
fetchBaseQuery
now correctly combines global options with endpoint / default options in all cases.
New Options
fetchBaseQuery
now supports a jsonReplacer
option that will be used when processing JSON.
Both dev check middleware now support regular expressions in the ignoredPaths
array in addition to strings. This adds extra flexibility in skipping certain fields.
TS Changes
The CaseReducer
type was sometimes incorrectly inferring its return type in rare cases. That's been fixed.
The isAnyOf/isAllOf
matcher function TS types have been tweaked to not require an individual first parameter. This allows spreading arrays of matchers as arguments, like const isLoading = isAnyOf(...interestingPendingThunksArray)
.
Other Changes
The serializableMiddleware
now uses a WeakSet
if available to cache values it's seen. This should significantly speed up checks against large state values in development builds.
What's Changed
- fix CaseReducer to infer from argument, not return value by @phryneas in #3054
- fetchBaseQuery | Add jsonReplacer param by @tophep in #2904
- Support RegExp in ignoredPaths/ignoredActionPaths by @markerikson in #3129
- fix(types): export
ThunkWithReturnValue
interface by @giomogna in #3108 - remove unnecessary fetchBaseQuery defaults by @phryneas in #3062
- make isAnyOf friendly for mapped matchers, but making argument optional by @megagon in #3123
raceWithSignal
method instead ofPromise.race
by @phryneas in #3021- Fix lint problems and enable linting on CI by @thorn0 in #2992
- Add caching to serializableStateInvariantMiddleware by @GeorchW in #3115
- Allow TS isolatedModules flag to be set for safer transpilation by @matmannion in #2911
Full Changelog: v1.9.1...v1.9.2
v2.0.0-alpha.1
This is an alpha release for Redux Toolkit 2.0. This release has breaking changes.
Changelog
ESM Migration
As a literally-major part of the Redux Toolkit 2.0 alpha development work, we've migrated the package definition to be a full {type: "module"}
ESM package (with CJS still included for compatibility purposes).
We've done local testing of the published package in several different build tools and environments:
- Vite 4
- Create React App 4 and 5
- Next 13
- Parcel 2
- Node 18 (importing as CJS and ESM)
We have not tested it in React Native projects yet, or other non-React projects.
So far, the package structure seems to work okay in each of those environments, but we ask the community to try out this alpha in your own projects and report any breakages you find!
While it's not strictly related to the ESM migration, one potential compat issue is that we no longer transpile any of our build artifacts (other than removing TS syntax), and we do use the optional chaining operator ( ?.
). It's likely that Webpack 4 will find the correct ESM build artifact, but not be able to parse that syntax. You'll need to either upgrade to Webpack 5, or modify your Webpack config to transpile the RTK build artifacts that are imported from node_modules
.
Redux-Thunk 3.0 Alpha
Along with the RTK package, we've migrated redux-thunk
to ESM as well and published that as 3.0.0-alpha.1
. That release also drops the existing default export, and instead has named exports: import { thunk, withExtraArgument } from 'redux-thunk'
.
This should not meaningfully affect RTK users, as configureStore
already sets up the thunk middleware for you.
Vitest Migration
We've migrated our own test suite from Jest to Vitest, fixing a couple of compat issues.
Related Future Work
Michel Weststrate, author of Immer, has published a roadmap for Immer 10.0. This includes modernization by dropping non-Proxy
ES5 compat, dropping the default export, performance improvements, and more. We plan to include Immer 10 in RTK 2.0.
We're restarting discussion around possible additional changes to Reselect in a v5 major version, and would appreciate feedback on possible improvements there.
See the RTK 2.0 planning thread for other work we're considering for 2.0.
What's Changed
- Migrate the RTK package to be full ESM by @markerikson in #3095
- Migrate RTK test suite from Jest to Vitest by @markerikson in #3102
Full Changelog: v2.0.0-alpha.0...v2.0.0-alpha.1
v2.0.0-alpha.0
This is the initial alpha release for Redux Toolkit 2.0. This release has breaking changes.
Please try this out and let us know of any build or runtime incompatibilities beyond the expected breaking changes!
See the RTK 2.0 planning issue for discussion of likely upcoming changes.
Changelog
Removal of Object Object Argument for createReducer
and createSlice.extraReducers
As described in the RTK v1.9.0 release notes, we've removed the object form for createReducer
and createSlice.extraReducers
. Use the "builder callback" form instead.
See the 1.9 release notes for examples of what the necessary changes look like, and details on the available codemod for automatically making this change to your source.
Modernized Build Output Formats
This release drops backwards-compatibility aspects for IE11 in our published package build artifacts:
All module formats (CJS and ESM) now contain code that targets the latest ES spec and no longer backwards-compiled to ES5 syntax
Later 2.0-alpha releases will add full Node ESM support with exports
in package.json
, and may contain other build artifact changes as well.
Build Tooling Updates
We've updated our own build process to use the latest ESBuild and TS versions.