Repository navigation
Redux Toolkit v2.x and v3.0 roadmap #5536
markerikson
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
I'm excited to announce an initial roadmap towards Redux Toolkit 3.0!
I have a lot of thoughts and ideas I've been bouncing around for years, and far more research docs than can fit into a Github post :) This writeup is an attempt to lay out these thoughts in a coherent plan, share where I think Redux should go in the near future, cover the scope of the probable work, list the likely breaking changes, and start getting user feedback on what you need and would like to see as we go forward.
TL;DR: RTK v3 will ship ESM-only, improve customization for RTK Query and
createSlice, and have a modest set of breaking changes aimed at improving usability and DX. Leading up to that, in 2.x we'll clean up internal implementation for more consistent and documented behavior, and ship a number of frequently-requested new features as well as some opt-ins for 3.0 behaviors.We're starting the planned 2.x work right away, and expect that 3.0 might ship in roughly 6-8 months.
You can browse through the overall roadmap and see the workstreams, issues, and planned releases via the main roadmap issue:
and we've opened some discussion threads to get feedback on specific aspects of the roadmap:
But first, the obligatory history lesson! Let's talk about how we got here and where things stand today.
A (Brief I Mean It) History of Redux
Redux was built and launched in summer 2015. Over the next 3 years it became a critical part of building apps with React, and its UI-agnostic core also let it be adopted with other frameworks.
However, the early usage patterns were highly verbose - a combination of the patterns shown in our docs, Redux opting for explicit behavior and indirection as an intentional architectural choice, and many of the usage approaches chosen and propagated by the community themselves. This led to the infamous "boilerplate" label, which sadly is still the (outdated) reputation many still assume about Redux today. The minimal size of the Redux core also meant that every team was building their own overlapping addon libraries to solve the same sets of use cases. Finally, the emphasis on "side effects" and pluggability led to extremely verbose codebases, especially when it turns out that 98% of "side effects" were just "fetch some data from the server and cache it on the client".
In late 2019, we shipped Redux Toolkit, our official standard library for building real-world Redux apps. We built RTK with several goals in mind: provide built-in solutions for the most common Redux usage patterns; learn from the myriad community add-on packages and standardize the best approaches; and resolve the "boilerplate" concerns by providing APIs that had good defaults and minimized the amount of code needed to use Redux.
Redux Toolkit succeeded in all those goals. We rewrote our tutorials in 2020 to teach it as the correct and standard way to use Redux, and we've had strong and consistent feedback since then that RTK makes using Redux straightforward.
The React ecosystem learned that "server state" and caching were really their own separate problem space. With the release of React hooks, we saw libraries like TanStack React Query, Apollo, and SWR provide hooks to encapsulate fetching and caching server state. Server state was always a common use case for Redux long before that term was coined, and much of the "boilerplate" complaints were really about having to hand-write data fetching logic.
In summer 2021 we shipped RTK Query, a data fetching layer built into Redux Toolkit. We took inspiration from many other libraries in the ecosystem, but built it on top of the core Redux concepts already in RTK: reducers, thunks, and middleware. We also designed it to work great with TypeScript and shipped an OpenAPI codegen. Today we teach RTKQ as the standard way to fetch data in Redux apps, and have seen it be widely adopted.
In late 2023 we shipped a wave of major versions for all our Redux packages. The primary goal was shipping dual CJS/ESM package definitions. This turned out to be incredibly hard to get right, but the pain was worth it to keep Redux working right for our users out of the box. In order to ship RTK 2.0 and avoid delays, we intentionally cut scope and did not make any breaking changes to RTK Query in 2.0, and instead said "we might do a 3.0 soon after with breaking changes".
It's now late 2026, three years later :) We're still on RTK 2.x. We still haven't shipped any breaking changes for RTKQ
Time to change that :)
Rationale for Change
Like any library, our codebase has grown over time. Every maintainer tries to build APIs that solve problems for our users... and then our users try to use those APIs in ways we never dreamed of or intended :) Features get requested, PRed, and added iteratively. These decisions often make sense in isolation, but because there wasn't a fully coherent plan behind them, the changes layer on top of each other organically, and this leads to complexity.
RTK Query,
createSlice, and the rest of RTK are powerful, battle-tested, and widely used. The concepts are well known, the implementations are solid, and we've covered the majority of use cases our users have asked for and needed.But, there's still a lot of rough edges. The types and internals are complex, some of the options and features don't cleanly interact with each other, and there's more features and use cases we'd like to cover that we can't handle now due to limitations in the current types and implementation.
So, the main goal for 3.0 is:
Clean up and refine each part of RTK, review and rethink our behaviors and implementation details based on a coherent set of goals and designs, and intentionally make breaking changes as necessary to polish the rough edges and enable new features we want to build.
On a scale of "Angular 1>2" to "React 18>19", this is pretty much a "React 19" scale of changes. The majority of your code won't need to change, we'll provide codemods and guides on how to migrate and update, and the intent is that any breaking changes justify themselves in better DX and usage going forward, with minimal actual upgrade pain for you.
RTK 2.x Improvements
The good news is that a lot of the work we're planning on doing will actually ship in 2.x releases as bugfixes, new options, and new features.
We've got an initial plan for the next few releases, each one focused on a different area of behavior. These may change as we go along, but the list looks pretty good at the moment.
2.14: Internal Correctness and Performance
2.15: Defined Behavior for RTKQ Requests
undefinedresults2.16: RTKQ Cache Entry Write/Update Semantics
upsertQueryEntriesremoveQueryDatautil2.17: Hydration and Suspense, 3.0 Prep
hydrate/dehydrateutils with versioned schemasrespondToalias forextraReducersLater 2.x:
injectEndpointsnamespacinggetTodosresponse to upsert togetTodoByIdentries)Primary Planned Changes for RTK 3
Looking farther ahead, here's the primary items we're planning on doing for RTK 3. This list is not exclusive, and trust me there's a lot more ideas beyond this :) But this should give a good sense of the direction and scope of the changes.
Update Packaging to Ship ESM Only
The work we did to ship dual CJS/ESM in 2023 was tough, but necessary given the state of the ecosystem. Today, things have changed significantly. Node 22+ supports
require(esm)(thanks Joyee!), and numerous other libraries have already gone ESM-only in the past year. Our packages will go ESM-only as well.This will cut down on installed size on disk, and simplify our own build and publish process. Like in 2023, we'll ship major versions of all our packages together at the same time. This is really the biggest motivator for shipping a set of majors.
Restructure RTKQ
createApiTypes and DefinitionsWe've got multiple future enhancements in mind for RTKQ, and some of those will require breakage.
Currently, the
createApiexported from the/query/reactentry point is an entirely separate definition from the "core" export. It has the "React module" baked in to add support for generating hooks. Unfortunately, there's no way to start with a "core" API instance, and then add the React support to it after it's created. This makes some use cases difficult, like trying to initiate a data fetch via an RTKQ API instance in an RSC environment that doesn't support hooks.We're going to revamp the current "module" approach for extending
createApi. We're still working out the details, but we do already have a prototype for taking a plain "core" API instance and adding React support to it later at runtime, similar to howapi.injectEndpoints()works.We're planning on changing the
queryfield in endpoints to berequest. Part of it is just the naming clash withbuild.query(), some of it is that there's aqueryfield inbuild.mutation()endpoints too and it feels weird. We might also change thebuild.query()definition to break out endpoints that need aqueryFninto abuild.query.fn()call, which may make the types a bit simpler and faster. (This rename is open for feedback - would appreciate opinions for and against the rename.)We're going to restructure the
state.api.queriesshape. Currently,api.queriesis an object containing all the individual cache entries by cache key, likestate.api.queries["getTodoById(1)"]. We're going to change that to nest them by endpoint name, likestate.api.queries["getTodoById"]["getTodoById(1)"]. This will improve internal update performance, since thequeriesobject will have fewer keys that have to be copied for every store update. We've always treated this as a black box and not part of our official public API definition, but there's code in the wild that currently directly access the queries, likeObject.keys(state.api.queries).forEach()to do filtering by endpoint name, or similar. That code will break in 3.0.Better
createSliceCustomizationcreateSlicecurrently has some limited customization abilities viabuildCreateSlice(). That's also needed to make use of the partially built-in async thunk support.We're going to revamp the way you customize
createSlice, which should both improve tree shaking if you aren't using thunks in slices, and enable adding your own "creators" tocreateSlice(such as building your own drop-in addon for managing normalized slices viacreateEntityAdapter).Immutability Customization
Redux Toolkit has been built around Immer for safe and simplified immutable update logic since the very first prototype, and we've contributed multiple improvements to Immer's own packaging and performance since we rely on it.
We've seen several other "Immer-alike" immutable update libraries pop up with various benchmarks and perf claims. We've also had requests over the years to disable or remove Immer. Our answer has always been that we see using Immer as a non-negotiable due to simplifying immutable updates and eliminating accidental mutations.
We have some prototypes that make the immutability library swappable behind a standard interface. Assuming that works out, users could choose to replace Immer with a separate immutability library, or even no actual immutability library at all. (We think this is a bad idea, but if you really want to swap in a no-op lib and write all the nested spreads yourself, it's doable.)
Rename
extraReducerstorespondToNaming things is hard. Especially so for library APIs. Those choices are also practically permanent. When you ship a new library API, you're essentially committing to support that feature and that syntax for life :)
All the way back in RTK 0.4.1 in Jan 2019, I added "the ability for a slice to respond to other dispatched actions". I didn't have a great idea for the name, so I called it
extraReducersand said I was open to bikeshedding other names.Well, guess what: we shipped 1.0 and we were stuck with it :)
We've gotten some complaints over the years that it's a stupid name. Honestly, I agree, and I take the blame for that :) (IT'S NOT LIKE ANYONE ELSE HAD ANY BETTER SUGGESTIONS AT THE TIME!)
So for 3.0 we're planning to rename
extraReducerstorespondTo. Same syntax, just change the name. It's breaking, but hopefully that makes things just a bit more readable and understandable.This will ship as a new alias in 2.17 (planned).
extraReducerswill be marked as deprecated, then removed in 3.0 and throw an error.Redux Core and Thunk Changes
While not part of RTK directly, we're planning on moving the thunk middleware into the actual
reduxcore package and marking theredux-thunkpackage as deprecated. It's one less package for us to manage, RTK relies on thunks, and it's reasonable to build that into the core. We might also add the semi-commonreduceReducersutility into the core as well.Other Possible Breaking Changes
Some of the other ideas in the works:
Per above, the RTKQ "module" system will go away in its current form. Best as I can tell it's mostly being used to let people pass in their own custom React hooks with a custom context, occasionally for the
unstable_sideEffectsInRenderoption. This has always been a very complicated set of internal impl code and delicate TS types, and I'm hoping we can find a better approach here.unstable_sideEffectsInRenderwill probably go away.Historically we've tracked DefinitelyTyped's policy of "last 2 years of TS versions". Here, the minimum supported TS version will jump to TS6, and we're working out what the policy will be going forward.
And to go along with all this, codemods / lint rules / migration guides / whatever else can help make it easy and straightforward to update to 3.0, as well as a set of "ecosystem CI" projects that we can use to test out various migration scenarios.
Other Future Enhancements
We've got a laundry list of ideas and possible improvements beyond 3.0 and breaking changes. Here's a few of the possibilities:
skipat the endpoint level instead of just in the hooksTimeline
"However long it takes" :)
As always, we're doing this in our spare time, and this is a lot of work :) So, this all ships when it's ready.
The good news is that RTK 2.x is solid and there's no urgent need to get 3.0 out the door. We can take the time to get all of this right and ship when it's ready.
We also already have prototypes for the biggest internal rewrites, like the RTKQ options and module extension, and the
createSliceoptions and immutability configuration. It seems like the hardest technical blockers are already proven out, and now we have to figure out how to productionize those and do the other 90% of the work.We've built out a pretty solid 2.x roadmap, and will immediately start work on that, beginning with some of the obvious bug fixes and perf improvements. Shipping some of the bigger features will take more time, particularly things like Suspense support.
We'll cut a 3.0 integration branch in the near future to start working on some of the packaging updates and other breaking changes - hopefully that will give people a chance to try those out and give us feedback.
At a rough guess, 3.0 might ship sometime in the next 6-8 months, depending on progress.
Planning and Feedback
We'll be conducting more research and trying to flesh out the plan for ourselves, nailing down specifics and clarifying unknowns. This will cover a lot of moving pieces. We're primarily tracking this via the set of roadmap / workstream issues in the RTK repo:
We'd love to get the community involved in this process!
The biggest thing we need is real-world feedback and suggestions. We'd love to hear from our users on what they want to see in future RTK releases and the biggest pain points you're dealing with, as well as feedback on the proposed changes above. Please see these discussion threads and let us know what you'd like to see and what could be a problem:
While we expect to do the work ourselves as maintainers, it's also possible for the rest of the community to contribute as well. This is the first time we've done such an extensive planning process for future work :) Part of that goal is to allow more folks outside the Redux team to help out if interested, by making the plans public.
We don't have a formal AI policy written up yet. Speaking for myself, I use agents to build software, but do so with a focused effort to carefully drive the work and understand what I'm building. Anything I ship has my name and reputation behind it, so I need to understand and stand behind any PR and issue I work on. I would ask for the same care and intent from anyone interested in contributing.
Our goal for Redux is that it should be a solid and flexible tool for building apps, and that if you choose to use it it should work exactly as advertised. RTK 3.0 should make that even more true.
Thanks, and here's looking forward to many more years of Redux!
All reactions