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

[RFC]: Would it make sense for createSlice to be able to automatically create asyncThunks the way they automatically create standard actions? #1362

Closed
njradford opened this issue Jul 28, 2021 · 8 comments

Comments

@njradford
Copy link
Contributor

njradford commented Jul 28, 2021

Pardon my ignorance if there's a prior discussion about this somewhere. I just noticed that it could potentially be useful to allow createSlice to auto generate the set of actions created by createAsyncThunk. This would in theory happen the same way that declaring reducers in createSlice auto builds a standard action. Currently I believe the only way to respond to async actions from a create slice reducer is with extraReducers, which is not at all a blocker right now.

This is an example basically of what I was envisioning:

https://gist.github.com/njradford/9bf5a95245cd3eee4a8f4c34efc3091c

Nothing about this is urgent or a bug. Just curious what maintainers thoughts were on further consolidating the interplay of standard actions, async actions, and their reducers into one createSlice call like this. Personally I've found leaning into createSlice very useful for keeping all the gears of the state machine in one place so it seems like it could also be useful to describe async thunks there as well.

On the other hand, extraReducers is in no way a pain to use. I generally declare the async thunks in the same file as the slice (ducks style). It just dawned on me that I only ever seem to use extraReducers to wire up listeners for async actions. And generally these aren't async actions that will impact several reducers at once.

Perhaps redux query papers over this as well?

@phryneas
Copy link
Member

We tried something similar that included adding the whole asyncThunk payload creator in there, but that essentially broke with TypeScript due to circular type imports. And we don't want to ship a feature without TS support.

See #637

Also, we expect that cAt will be used a lot less now that RTK Query is out so we have put it off for now.

@markerikson
Copy link
Collaborator

Yeah, we'd love to do this, but the difficulties getting it typed correctly with TS are a blocker.

@njradford
Copy link
Contributor Author

Thank you both for the explanation. The links to the prior threads provide a lot of context so I'll close this.

As an aside, is there a roadmap of "things that would be great but are blocked by [quirk of tool that could be fixed in future]?". Mainly to refer to if something like TS ever publishes API changes that could resolve this use case (which seems possible since they seem to be constantly expanding to accomodate weird quirks).

@markerikson
Copy link
Collaborator

Mmm... not specifically. We don't have much of a formal roadmap laid out.

Purely off the top of my head, atm the general plan is:

  • 1.7: RTKQ SSR and Suspense support
  • 2.0: drop IE11 support and maybe clean up some bits of the accumulated APIs

There are several open issues with various suggestions and "wouldn't it be nice if...?" discussions, but not much concrete atm.

@njradford
Copy link
Contributor Author

Mmm... not specifically. We don't have much of a formal roadmap laid out.

Purely off the top of my head, atm the general plan is:

  • 1.7: RTKQ SSR and Suspense support
  • 2.0: drop IE11 support and maybe clean up some bits of the accumulated APIs

There are several open issues with various suggestions and "wouldn't it be nice if...?" discussions, but not much concrete atm.

That makes sense. I'm not really sure the best way to even convey a roadmap short of a .plan file. Is something like that of interest at all to the maintainers? It looks like milestones are already used in the issues section of the project. Dunno if that's a good place for such info.

@markerikson
Copy link
Collaborator

markerikson commented Jul 30, 2021

Milestones or issues, either would work.

We just don't have enough of a real roadmap atm for us to have tried writing one out :)

Closest is #958 , the "RTK 2.0?" issue

@jondot
Copy link
Contributor

jondot commented Jan 13, 2022

Sorry to necro-bump this thread. But I was following the same path as @njradford and ended up with the same kind of sketch - and this thread has been really helpful at explaining the reasons (thanks!).

Wanted to add one more question on top of that in the same direction, could you elaborate why extraReducers was picked to be a function?
As opposed to something like this (a straight builder-to-struct conversion)?

extraReducers:{
  addCase: ...
  addMatcher: ...
  defaultCase: ...
}

EDIT: turns out it can do both. sorry for the bother, leaving the original question for other people as well.

@markerikson
Copy link
Collaborator

@jondot : you can write extraReducers as an object, and in fact originally that was the only way to use it:

https://redux-toolkit.js.org/api/createSlice#the-extrareducers-map-object-notation

However, that approach does not work well with TypeScript. TS doesn't recognize that action creators can be implicitly stringified, so it shows errors if you do [someActionCreator]: someCaseReducer. You have to do [someActionCreator.type] (Which works, but is a bit annoying.

Beyond that, there's a bigger issue. There's no way for TS to know just based on the string key what the actual TS type of the action object or the state are. That means you have to duplicate whatever TS types are applied to initialState in the slice and the action from the action creator.

Additionally, this only lets you respond to individual specific actions.

The builder notation solves those problems:

  • You can just pass the action creator as the argument to builder.addCase()
  • TS will automatically infer the types of state and action
  • You can use builder.addMatcher() to write significantly more flexible matching logic
  • We were also able to add builder.addDefaultCase() to fill a small missing gap in functionality

See https://redux-toolkit.js.org/api/createSlice#the-extrareducers-builder-callback-notation

I'm actually debating removing support for the object form in a future RTK 2.0, on the grounds that it doesn't provide enough benefit. The number of lines of code is almost the same with the builder form anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants