Closed markerikson closed 11 months ago
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
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:
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.
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:
.../compat
for every entry point that would also target IE11 (only this build would contain enableES5
)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.
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!
@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.
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.
Here's my thoughts atm:
exports
field in package.json
is effectively a breaking change due to Node compat concerns, so we can't do that yetSo. 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.
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?
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 #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-casesHow about state persistence for offline support?
@grumpyTofu Not sure what you're suggesting there. File a separate issue / discussion thread to provide details?
@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?
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.
Note for later reference - Sindre Sorhus has a big gist with instructions on switching to pure ESM:
https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
Added an issue noting that we should mark the object case reducer syntax as deprecated with a runtime warning:
Per https://github.com/reduxjs/redux-toolkit/issues/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".
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:
Dropping a key link in here about how to improve package publishing:
https://github.com/frehner/modern-guide-to-packaging-js-library
Hypothetical idea. The types for createSlice
are a pain, and part of that is the need to deal with prepare
callbacks.
Asked Lenz about it and he pseudo-coded something like this as an idea to investigate:
const slice = createSlice({
...,
// make this a callback
reducers: (build) => ({
normalReducer(state, action: PayloadAction<foo>) {
...
},
somePreparedReducer: build.preparedReducer(
// prepare
(a: number, b: string) => ({ payload: a, meta: b }),
// reducer
(state, action) => {
...
}
)
})
})
(edited by Lenz to make it more feasible)
Also, something to consider:
slice.name
, or add a new slice.reducerPath
option.slices
option to configureStore
combineSlices
function that combines an array of slices into a reducer (and as a second argument, also accepts a reducer map object)This would be good groundwork to add a selectors
field to createSlice
. Per default (or only if slice.reducerPath
is set), there could be slice.selectors.foo
on the slice
object. For slices mounted somewhere else, there could still be a slice.getSelectors(rootState => sliceState)
function.
A couple more Twitter requests for RTK 2.0 ideas:
and a poll on Redux code-splitting usage:
More thoughts: see if we can optimize our TS types performance (like, time it takes TS to parse things).
Ref thread: https://twitter.com/AndaristRake/status/1574836992214536193
TanStack Query is discussing changing their cacheTime
flag (equivalent to RTKQ's keepUnusedDataFor
option) over here:
https://github.com/TanStack/query/discussions/4252
might be worth considering seeing if there's a couple ways we could align our APIs for consistency.
Check to see about turning on TS's declarationMap
option for better "Go To Definition" behavior:
Lenz is tossing around ideas for maybe having some form of selectors built into createSlice
, and also maybe a combineSlices
helper:
Some PRs that got accidentally closed with 1.9 merging:
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 theinjectEndpoints
approach, as a consequence of which I cannot have more than onegetPokemon
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 thereducerPath
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.
@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.
@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.
@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.
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
@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.
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.
@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.
@phryneas There is actually an open issue and PR.
https://github.com/reduxjs/redux-toolkit/issues/1441 https://github.com/reduxjs/redux-toolkit/pull/2953
It looks like the PR is part of the 1.9x milestone though.
neat post from the tRPC folks talking about profiling and improving TS compilation perf for their types:
neat post from the tRPC folks talking about profiling and improving TS compilation perf for their types:
There's also a page in the TS wiki on optimising performance.
I'm glad to see RTK Query support rRPC at v2.0.
@ryota-murakami I don't think we'd be adding anything specific related to tRPC. Also, doesn't it already use React-Query internally?
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 !
@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!
Thank you for the quick answer, very appreciated ! (My comment on the long time was not a complaint also, just an observation :wink:).
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.
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:
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.
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.
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:
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!
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:
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 :)
@markerikson Oh, about 2 weeks later? That's good feeling! From me..
export
keyword.@ryota-murakami could you file a separate issue showing what you're trying to do with those types?
@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.
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 PANICOkay, 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?