Skip to content
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

Future planning: RTK 2.0? #958

Closed
markerikson opened this issue Mar 29, 2021 · 51 comments
Closed

Future planning: RTK 2.0? #958

markerikson opened this issue Mar 29, 2021 · 51 comments
Labels
enhancement New feature or request maintenance
Milestone

Comments

@markerikson
Copy link
Collaborator

markerikson commented Mar 29, 2021

UPDATE 2023-12-05 We're live! https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0

## UPDATE 2022-10-15: THIS IS NOW MUCH LESS HYPOTHETICAL AND HOPEFULLY HAPPENING SOON-ER THAN LATER!

## THIS IS HYPOTHETICAL AND WE ARE NOT GOING TO BE RELEASING RTK 2.0 ANY TIME SOON PLEASE DON'T PANIC

Okay, with that disclaimer out of the way: what would an RTK 2.0 look like? What "breaking" changes would we want? When should we actually consider doing that?

The most obvious ones I can think of would involve changing back-compat publishing stuff. In particular, dropping the default enableES5() plugin call for Immer, and dropping publishing IE11-compatible syntax from our published build artifacts.

Related Twitter thread:

I suppose the hypothetical Redux 5.0 with potentially altered TS types might fit in there, but I truly have no idea if we're ever going to get around to releasing that.

Right now we're planning to put RTK Query out in RTK 1.6. It's additive, so it's not breaking.

The ESBuild PR in #957 is problematic for IE11 compat out of the box, but it's likely we could down-compile the ESBuild output to resolve that.

Any further ideas?

@crutchcorn
Copy link
Member

Just curious; what would be the blocker for Redux 5.0? I apologize, I missed that discussion and thought it would be useful to include it as something to track in this discussion

@markerikson
Copy link
Collaborator Author

markerikson commented Mar 29, 2021

So if you look over in https://github.com/reduxjs/redux on master, the Redux core was actually converted to TS almost two years ago.

And it's just sat there ever since, unreleased.

Sorta related to that, there's some changes to the redux-thunk typings that have been sitting around unreleased for a very long time.

There's a couple different potential things here:

  • @timdorr was overseeing both of those changes, and he's been extremely busy with his day job for a while now
  • A major release of any lib is always a big deal, and there's a lot of Redux-related packages that might need to get updated to say they work with 5.x
  • For TS specifically, there's almost definitely some breaking changes in the Redux core TS types, either because something got "fixed" during the TS conversion, or something accidentally got broken

Meanwhile, Redux 4.x works just fine, both code and types.

So, basically it's about no one prioritizing the effort, combined with concern about breaking the ecosystem (and potentially for not much real benefit).

I am planning to put out a new Redux 4.1.0 release in the near-ish future that would extract our error messages to "error codes" to shave down prod size, tweak a couple error messages, and remove the remaining deps like `symbol-observable. I want to get that into RTK 1.6 too.

But at this point, we have no real plans to actually get Redux 5.0 out the door.

@phryneas
Copy link
Member

phryneas commented Mar 29, 2021

So my thought is that RTK-Query would actually be a "big enough addition" to actually "sell" a 2.0, compared to a tooling change.

As for the bigger changes I'd include:

  • RTK-Query
  • entityAdapter indices
  • add ESM "modern" build targeting transpilation/bundlers
  • add ESM build targeting browsers
  • keep CJS build, pretranspiled with a target for all modern browsers
  • add a new CJS entry point .../compat for every entry point that would also target IE11 (only this build would contain enableES5)

@markerikson
Copy link
Collaborator Author

My inclination at the moment would be to actually do most of that in RTK 1.6 or 1.7.

Most of that is additive - either new APIs or new build artifacts. Agreed that major version numbers can also be used to indicate "big new features", but I see this as more of a parallel to React Hooks coming out in a 16.8 minor, and 17.0 being used for just compat and cleanup.

I think that doing it as a minor build would make it a bit easier for folks who are using RTK to get the new RTK Query functionality more automatically.

@rocon4
Copy link

rocon4 commented Mar 29, 2021

Any further integration of RTK Query into Redux Toolkit would be awesome. I've been switching a lot of simple fetch/ mutation requests that were originally in slices over to it (new to React/ Redux in general so I was placing a bit too much in Redux Toolkit). My code has slimmed down quite a bit already, however occasionally I want to update a piece of global state in redux through extraReducers from an RTK Query mutation. I'm not sure if this is currently possible or even advised too if it is (can't find in the docs). Cheers!

@markerikson
Copy link
Collaborator Author

@rocon4 yep, and that's why we're planning to merge the RTK Query functionality back into the RTK package itself - to have it all right there and accessible without needing to install other packages (which, in some cases, may ease corporate approval processes and such).

Usage questions probably oughta go over to a Discussion thread or Reactiflux, but off the top of my head, I think you could import the thunks that are auto-generated by createApi into your other slice files and handle those actions there as well, just as if you'd called createAsyncThunk yourself and were wanting to handle that in a slice.

@msutkowski
Copy link
Member

Any further integration of RTK Query into Redux Toolkit would be awesome. I've been switching a lot of simple fetch/ mutation requests that were originally in slices over to it (new to React/ Redux in general so I was placing a bit too much in Redux Toolkit). My code has slimmed down quite a bit already, however occasionally I want to update a piece of global state in redux through extraReducers from an RTK Query mutation. I'm not sure if this is currently possible or even advised too if it is (can't find in the docs). Cheers!

@rocon You for sure can. All endpoints have matcher properties on them.

extraReducers: (builder) => {
    builder
      .addMatcher(
        api.endpoints.yourEndpoint.matchFulfilled,
        (state, { payload: { result } }) => {
              // do things with the result
        }
      );
  },

Feel free to jump on reactiflux or file an issue in the rtkq repo before it gets merged in if you have any issues. It's on my list to update in the examples as more focus will be on integrating with RTK specifically in the near future.

@markerikson
Copy link
Collaborator Author

Here's my thoughts atm:

  • We just merged in the big TDX->ESBuild conversion over in chore(build): move tsdx to esbuild #957 . The build artifacts we're generating should effectively match what we've had so far: ES5 syntax and IE11 compat for CJS/ESM/UMD, plus a new set of "modern" artifacts that target bundlers and browsers. So, in theory, none of the build changes should be breaking yet.
  • I want to get the RTKQ stuff out in a minor build to help increase the initial uptake on that. Plus, it's all additive APIs, much like React released hooks in a 16.8 minor. (I can also see an argument for only releasing those in a 2.0 as a carrot to get people to upgrade, so I'm willing to listen to debate on this point.)
  • It sounds as if including an exports field in package.json is effectively a breaking change due to Node compat concerns, so we can't do that yet
  • I'd notionally assumed that RTK 2.0 would include Redux 5.0 whenever that happened, but we still have no concrete plans to release Redux 5.0 any time soon
  • However, Tim recently mentioned to me that he might have some time to look at the Redux 5.0 work in the semi-near-ish future.

So. My plan atm is to go ahead and continue with this next release as RTK 1.6, including the build tooling changes and RTKQ. We'll keep IE11/ES5 compat for now. That minimizes changes and gives more people a chance to adopt RTKQ out of the box.

We'll hold off on a 2.0 release for now. When it's time to do that, we'll drop IE11 compat and probably the UMD builds. It would be nice if we had a Redux 5.0 release ready to go so that we can sort out all the potential TypeScript issues that are likely to occur as part of that.

@markerikson
Copy link
Collaborator Author

I suppose another set of questions is, what about our actual APIs would we want to drop or change that would be breaking?

I'll toss one out: the object syntax for createReducer and createSlice.extraReducers. Might be a bit controversial, especially given that it was a bit of a selling point for RTK early on, but given that we strongly emphasize the builder syntax at this point I think it's justifiable.

Any other suggestions?

@markerikson markerikson added enhancement New feature or request maintenance labels Jun 7, 2021
@Shrugsy
Copy link
Collaborator

Shrugsy commented Jul 7, 2021

A couple others that could potentially be dropped:

  • getDefaultMiddleware export - The callback notation for the middleware property is superior in the high majority of cases given that it will be pre-typed (note that I've opened 🗑 📝 Deprecate getDefaultMiddleware export #1258 to deprecate it already)
  • unwrapResult export - Now that the dispatched thunk from cAT has an unwrap property directly, I don't think there are many use cases for using unwrapResult explicitly. However, given that it can be called on the action rather than the promise that resolves to the action, it theoretically enables alternate use-cases

@grumpyTofu
Copy link
Contributor

How about state persistence for offline support?

@markerikson
Copy link
Collaborator Author

@grumpyTofu Not sure what you're suggesting there. File a separate issue / discussion thread to provide details?

@grumpyTofu
Copy link
Contributor

@markerikson based on the previous discussion, it looks like you are looking for ideas that could be really cool and significant enough to substantiate a '2.0' release, right? RTK Query already solves caching, so what about making everything else persistent? Or maybe adding some online/offline listeners to api slices so that a query could detect if the user is offline and manage the state of whatever a user would do while offline and subsequently make necessary api calls once the connection is restored?

@markerikson
Copy link
Collaborator Author

Sort of. I actually saw a comment from someone in the Ember community the other day along the lines of "minor versions are for new functionality, majors are for removing deprecated things" - ie, a major actually shouldn't have much big new stuff. I can kinda see the point in that.

Offline stuff is its own entirely complicated area, and I don't think it's anything any of us maintainers have any experience with. That's part of why I suggested opening up a separate thread - it'd be easier to discuss what "offline support" even means, sketch out potential requirements, and figure out if it's a thing we'd even want to try doing.

@markerikson
Copy link
Collaborator Author

Note for later reference - Sindre Sorhus has a big gist with instructions on switching to pure ESM:

https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

@markerikson
Copy link
Collaborator Author

Added an issue noting that we should mark the object case reducer syntax as deprecated with a runtime warning:

#2301

@markerikson
Copy link
Collaborator Author

Per #930 , we should consider replacing the current Dictionary<T> type in the entity adapter state, which treats values as T | undefined, with a simple Record<key, T> that just says "sure, this item always exists no matter what index is being used".

@markerikson
Copy link
Collaborator Author

We should also revisit a lot of our TS types and see if they can be simplified now that we're dealing with more modern TS (4.2+).

Vaguely related, someone was arguing on HN that their similar implementation is simpler:

@markerikson
Copy link
Collaborator Author

Dropping a key link in here about how to improve package publishing:

https://github.com/frehner/modern-guide-to-packaging-js-library

@markerikson markerikson added this to the 2.0 milestone Oct 26, 2022
@markerikson
Copy link
Collaborator Author

markerikson commented Nov 4, 2022

@markerikson
Copy link
Collaborator Author

markerikson commented Dec 29, 2022

Per https://www.reddit.com/r/reactjs/comments/zxcuvq/redux_fetch_react_useeffect_best_practices/j24eh8f/?context=5 :

The most common scenario that I am facing is that I would have different screens with different representations of the same entity (say, one screen is showing one set of pokemon data, whereas another screen is showing a somewhat different set of pokemon data), for which I would fetch different sets of data from the same graphql api. Ideally, I would just have one slice for one screen, and another slice for another screen; in which case both slices could have their own getPokemon method, each of which appropriate for a given screen. Instead, I find myself using a single api slice, split across screens using the injectEndpoints approach, as a consequence of which I cannot have more than one getPokemon method. Instead, I would have to come up with unique names for these endpoints (e.g. getPokemonForScreen1, getPokemonForScreen2, etc.).

This really breaks the notion of modularity. One would expect to be able to name things however one wishes within a single module, being safe in the knowledge that names are scoped within a module, and cannot clash with anything in other modules. But the injectEndpoints approach has the unfortunate consequence of losing this name encapsulation. This gets more noticeable the larger the project grows.

My thoughts:

I might have said this over there, but my first response would be that every tool has limitations, and this seems like a use case that is at the far reaches of what RTKQ is designed to do. Lenz had some particular design goals in mind when he created RTKQ, but the community has (not surprisingly) wanted to use the lib in dozens of ways we never could have foreseen ourselves. So, the case of "multiple representations of the same item" and "multiple screens needing those different representations" is something we simply have never even thought of doing ourselves, no one has brought it up before, and so nothing in RTKQ's design is intended to make that use case simpler.

Hypothetically, a potentially simple fix would be to update defaultSerializeQueryArgs to include the reducerPath value in the serialized name, like: "pokemonApi:getPokemon('pikachu')". Alternately, the internal slice reducer could switch to storing the values nested a level deeper, like: queries: {pokemonApi: {"getPokemon('pikachu')"}}, etc.

That said, it could cause a couple issues.

We do consider the internal data structure to be intentionally "opaque", ie, it's not specifically documented and users are expected to interact with it via the selectors and hooks rather than direct access. But, the values are just right there in the Redux store and visible same as any other pieces of the Redux state. So, changing that would cause the (relatively rare) cases where users are already introspecting the state themselves to break, because the key strings would have changed.

Also, the Redux DevTools Extension has an "RTK Query" tab, and I'm assuming it derives the endpoint names the same way, by inspecting the keys. That would also probably break if we changed the key format or state structure.

Given that we're looking at RTK 2.0, something like that could be on the table as a notional breaking change, but the question is whether this relatively rare use case is enough to justify it.

@phryneas
Copy link
Member

@markerikson this is pretty normal and for example Apollo Codegen has the same requirement - you can have a hundred GraphQL queries that query similar data, but each one of them should have a unique operation name.
That translates 1:1 to our endpoints.

@markerikson
Copy link
Collaborator Author

@phryneas : yeah, I think the complaint here is that "unique operation name" gets annoying when you have multiple conceptual representations of the same thing, ie, a "mini Pokemon" that might just be {id, name, type}, and another that might be {id, name, type, abilities}. They're both a Pokemon, so you might name both of the endpoints getPokemon and have a conceptual naming clash.

@phryneas
Copy link
Member

@markerikson Sure, but this comes up because they are using GraphQL, where it is pretty common to query the same thing twice, but with different properties - and my point is that this is a common problem between GraphQL tools. I don't think we can (or should) be the ones to solve it though.

@misterjame
Copy link

Is this correct repo to mention it? I'm using rtk query with graphql codegen and I am not able to use features like transformResponse

@phryneas
Copy link
Member

phryneas commented Jan 6, 2023

@misterjame Generally, this should be it's own issue - but using enhanceEndpoints you should be able to add transformResponse to a code-generated endpoint after the fact. Although that seems like something most people probably would not do with GraphQL.

@misterjame
Copy link

It would be nice to have all the bells and whistles. Can actually generate once and do everything I want but if I re-gen my changes get wiped. RTK Query has been a lifesaver for our project. Thanks guys. I'll leave you to it.

@phryneas
Copy link
Member

phryneas commented Jan 7, 2023

@misterjame and for that, you would use enhanceEndpoints* in another file*, so your changes do not get overwritten. But as I said, any questions about that would not belong into this issue. Please open a separate issue if you have questions on that that cannot be answered by the documentation on code generation and code splitting.

@misterjame
Copy link

misterjame commented Jan 7, 2023

@phryneas There is actually an open issue and PR.

#1441
#2953

It looks like the PR is part of the 1.9x milestone though.

@markerikson
Copy link
Collaborator Author

neat post from the tRPC folks talking about profiling and improving TS compilation perf for their types:

https://trpc.io/blog/typescript-performance-lessons

@terry-au
Copy link

neat post from the tRPC folks talking about profiling and improving TS compilation perf for their types:

trpc.io/blog/typescript-performance-lessons

There's also a page in the TS wiki on optimising performance.

@ryota-murakami
Copy link
Contributor

I'm glad to see RTK Query support rRPC at v2.0.

@markerikson
Copy link
Collaborator Author

@ryota-murakami I don't think we'd be adding anything specific related to tRPC. Also, doesn't it already use React-Query internally?

@davidgarry
Copy link

davidgarry commented Aug 24, 2023

Hello @markerikson @phryneas

It's a long time since the last comment on this version 2. I see that the beta 0 has been released in May. Do you have any timeline on when it will be officially released ?

We are particularly interested by the new feature "combineSlices API with built-in support for slice reducer injection for code-splitting". Based on when it would be released, it will determine if we go for now with a custom solution on our side in our production environment or if we wait a little 😄

Thank you !

@markerikson
Copy link
Collaborator Author

@davidgarry No specific time frame, but it's probably "several months". We need to do major releases of all our packages, simultaneously, and there's a lot of work (along with the fact that we do this in our free time - not a complaint, just an observation).

We would absolutely love for folks to try out the betas, both to tell us if anything unexpected breaks, and to give us actual feedback on the new APIs like combineSlices. I don't know if anyone has actually meaningfully used that yet, and getting real-world feedback on whether it A) works as expected, and B) needs tweaking, would be absolutely invaluable!

@davidgarry
Copy link

Thank you for the quick answer, very appreciated ! (My comment on the long time was not a complaint also, just an observation 😉).

So we will go with a custom solution for now, and regarding the beta one, I will try to plan a spike on our side to test it and provide feedbacks on what happened.

@markerikson
Copy link
Collaborator Author

markerikson commented Sep 15, 2023

Got asked about the status of RTK 2.0 in another thread and wrote up a longer answer, so I'll paste that here:

No specific target date, unfortunately, and it's probably going to be several months.

There's a not-well-specified but "large" amount of stuff that needs to be done across all our libraries so that we can publish them simultaneously.

The closest to a known list of stuff we know ought to be done just for RTK itself is in:

I did also try to do a skim through the other repos to get a sense of what things look immediately obvious to do, but don't have that list on hand atm.

On top of that, there's still a number of open questions:

  • What breaking changes should we make to the RTK Query API?
  • What future RTKQ features can we defer for after 2.0?
  • What changes do we maybe need to do now in order to make those later features possible?
  • What about all the codegen stuff?
  • What about proof-of-concept features like proxy-based tracking for selectors in Reselect and React-Redux?
  • We've added several new features like combineSlices and createSlice.selectors, but no one has really tried them out. We think they probably work and have tests... but is the API design right? Do those actually solve real problems? Do they solve problems the right way? Are there use cases we should be considering beyond those? Other API design changes?

We need to consider the rest of the docs work as well.

The next overall steps I need to do are putting on my PM hat and trying to nail down what the actual remaining scope looks like.

I don't want this effort to keep dragging on, and I don't want us to get bogged down chasing one potential feature after another. But given that this is the first major version bump we've ever done for RTK, I also don't know when we might do another one. So, I would rather err on the side of making sure we've covered as many bases as possible.

The other complication, of course, is that we're doing this in our spare time. (That is not a complaint - that's an observation). Lenz hasn't had much time to work on Redux since joining Apollo. Ben has done a lot of work building features, but not much on infra. I'm juggling Replay, Redux, other tasks, and trying to have something resembling a life :) (golf, friends, family, down time.)

I do want to focus on RTK work over the next few months, but it's all in my free time. With golf season ending, I may be able to put a bit more focus into it.

We don't have an actual migration guide written up. The closest to that would be reviewing each of the release notes entries for listed breaking changes - I've tried to be pretty thorough in that regard.

In theory, the biggest known breaking changes would be things like removing the object arguments for createSlice.extraReducers and a bunch of TS types tweaks to change AnyAction to UnknownAction.

So, my general suggestion is to literally try bumping your deps, see what compiles and fails, fix TS compilation issues, and see how your tests shake out.

@einarq
Copy link

einarq commented Sep 19, 2023

We've added several new features like combineSlices and createSlice.selectors, but no one has really tried them out.

Fwiw, I have tried these out, and they are very useful in my scenario. Means I get much improved TS support for something that I have some custom code for today, written years ago in plain js.

@markerikson
Copy link
Collaborator Author

Update on our status and plans:

One of the biggest concerns I had in my head was that we were presumably going to have to do some sizeable design work and breaking changes to the RTK Query APIs in 2.0 After all, this is our first major version release in 4 years, and my thought was "who knows when we'll do another major version?".

We have a large thread discussing potential RTKQ requests and changes in #3692: RTK Query API pain points and rough spots feedback thread. But, we haven't had any time to get together as a group and discuss potential changes, much less figure out which changes we want to make, and which changes might be breaking (and thus need to go in a major) vs those that are smaller and can be deferred, and then we'd still need to go and implement those changes.

This was a big mental block for me. I could foresee RTK 2.0 dragging on for months on end, and I didn't want us to get bogged down trying to work through those issues, especially since 2.0 has meaningful perf and bundling changes.

So, last week I tossed out a proposal to the team:

What if we deferred all changes to RTK Query and focus 2.0 solely on shipping the packaging changes and existing new features already merged into RTK... then do any RTKQ breaking changes in an RTK 3.0 release in the relatively near future?

In other words:

  • De-scope RTK 2.0 so we can get it out the door sooner
  • Be willing to do another major version relatively soon, but focus it on any RTKQ changes needed

We all agreed this was a good idea, and we're going to do that.

This means that I can now hopefully foresee us getting RTK 2.0 done in the next couple months ( 🤞🤞🤞), rather than dragging on endlessly.

The RTK 2.0 planning milestone has the major outstanding list of tasks that we're currently intending to get done before 2.0 is ready.

There's also any additional work needed to finish up major releases for Redux core 5.0, React-Redux 9.0, Redux Thunk 3.0, and Reselect 5.0.

At the moment, I'm hopeful that there actually aren't any real changes left for Redux, React-Redux, or Redux Thunk, and that Reselect won't require too much effort.

We'd still appreciate more feedback on the betas!

@markerikson
Copy link
Collaborator Author

Latest update:

We're hoping to publish RTK 2.0 + other packages no later than December 2!

We've done some further issue triage and code updates. At this point, there's basically 4 things left:

  • Final updates to Reselect (some possible API / feature tweaks, plus docs updates)
  • Some byte shaving to do on React-Redux
  • Final docs updates (migration guide, full list of breaking changes, any remaining API docs)
  • Syncing all the package version updates

We're still looking for any beta feedback! tbh we've gotten very few comments, and it's making me a bit nervous :)

@ryota-murakami
Copy link
Contributor

@markerikson Oh, about 2 weeks later? That's good feeling!
From me..

  1. export all React Query type as a package.
    Some internal type can import from app because these defined with export keyword.
    But within "moduleResolution": "bundler", cannot find these types unless exported from library entrypoint.

Screenshot 2023-11-15 at 6 07 41

  1. cli especially Slice template generation.
    Honestly I couldn't write from scratch each Slice file.
    I saw many fork setup template generator on a each project with plop, hygen.
    So I'm glad if there is built-in cli option for any Redux Toolkit files(store, typed hook etc) and makes easy facilitate adoption Redux Toolkit for team members!

@markerikson
Copy link
Collaborator Author

@ryota-murakami could you file a separate issue showing what you're trying to do with those types?

@ryota-murakami
Copy link
Contributor

@markerikson I just defined a MutationTrigger, which is an internal type of Redux-Toolkit, when giving the return of useMutation() as a function argument.
Exactly the same way as you give Dispatch<SetStateAction<S>>type when arguments and Props receive React's useState() update function.

It is the Library Author's decision whether or not to export the internal type, and if it is not exported from the entry point, the user just gets the internal type with the infer keyword, for example.

So this is not an Issue, but just a feature request.
The reason for this is that it is easier to import Redux-Toolkit types directly when they are needed.

@markerikson
Copy link
Collaborator Author

And 2.0 is live!

https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0

@markerikson markerikson unpinned this issue Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request maintenance
Projects
None yet
Development

No branches or pull requests