Skip to content

Suggestion: Update mapBuilders to make it easy to add thunks to a slice #2316

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

Closed
edishu opened this issue May 11, 2022 · 5 comments
Closed

Comments

@edishu
Copy link

edishu commented May 11, 2022

I've reviewed issues: #629 and #1045 and looks like due to TS complexity support for defining thunks in createSlice has not been possible.

However, a simpler solution can be adopted which can simplify many common use cases of using thunk in createSlice.
Adding a function like addAsyncThunk to builder object will help in setting loading conditions automatically for thunk related actions.

So presently when a user is adding thunk (myThunk) to a slice code looks like:

createSlice({
    name: "mySlice",
    initialState,
    reducers: {},
    extraReducers: (builder) => {
        builder
          .addCase(myThunk.pending, (state) => {state[loadingKey] = true})
          .addCase(myThunk.rejected, (state) => {state[loadingKey] = false})
          .addCase(myThunk.fulfilled, (state, action) => {state[loadingKey] = false; ...other updates})
    }
})

For a slice which has many thunks this becomes very long chain, hard to read and debug.
addAsyncThunk will simplify most common use cases in which pending/rejected actions only change the loading state.

So the above code will look like:

createSlice({
    name: "mySlice",
    initialState,
    reducers: {},
    extraReducers: (builder) => {
        builder
          .addAsyncThunk(myThunk, loadingKey: string, fulfilledCallback)
    }
})
@edishu edishu changed the title Update mapBuilders to make it easy to add thunks to a slice Suggestion: Update mapBuilders to make it easy to add thunks to a slice May 11, 2022
@phryneas
Copy link
Member

For what it's worth, this is possible to implement in userspace - if you know the trick:

import {ActionReducerMapBuilder, CaseReducer, AsyncThunk} from '@reduxjs/toolkit'
import {AsyncThunkFulfilledActionCreator} from '@reduxjs/toolkit/dist/createAsyncThunk'

function addAsyncThunk<S, Returned>(builder: ActionReducerMapBuilder<S>, thunk: AsyncThunk<Returned, any, {}>, loadingKey: keyof S, fulfilledCallback: CaseReducer<S, AsyncThunkFulfilledActionCreator<Returned, any, {}>>){
  builder.addCase(thunk.fulfilled, (s,a) => {
    s[loadingKey] = true
    fulfilledCallback(s,a)
  })
  builder.addCase(thunk.rejected, (s,a)=> {
    s[loadingKey] = false
  })
  builder.addCase(thunk.pending, (s,a)=> {
    s[loadingKey] = true
  })
}

This will still need a little more massaging around the types (I'm in a hurry), but it should show how you can do that with given tools already.

@edishu
Copy link
Author

edishu commented May 12, 2022

@phryneas this definition creates a standalone function addAsyncThunk. Extending createSlice such that addAsyncThunk is available in extraReducers callback argument improves usability. Otherwise users will have to know/remember to import addAsyncThunk.

@markerikson
Copy link
Collaborator

@edishu I think the point is that A) loading state handling is going to be unique to a given project, and B) given that it's relatively simple to write a function like this on your own, it's not something we would immediately want to build in to createSlice for now.

@phryneas
Copy link
Member

phryneas commented May 12, 2022 via email

@edishu
Copy link
Author

edishu commented May 13, 2022

@markerikson @phryneas Thanks for clarification! I can use a function like you have suggested.

@edishu edishu closed this as completed May 13, 2022
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

3 participants