-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add support for defining thunks in createSlice
#629
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
Comments
I think this last option looks great syntax-wise. My only concern would be about how easy it would be to have an
I can't really think of any other usage issues at this point. |
So I've created a kinda-somehow created something that almost works, but not quite. It looks like this: The problem here is that there is no way to have the const createSliceAsyncThunk = curryWithState<TestState>() which of course is very suboptimal. We could get around that, but again: only with a builder notation. And as Only feasible way for that would be to add a new key, so we'd end up with something like I initially described: createSlice({
name: 'test',
initialState: {} as TestState,
specialReducers: {
testInfer: create => create.asyncThunk(
(arg: TestArg, api) => {
return Promise.resolve({ payload: 'foo' } as TestReturned)
},
{
pendingReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
},
fulfilledReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
expectType<TestReturned>(action.payload)
},
rejectedReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
expectType<SerializedError>(action.error)
}
}
)
}
}) (and yeah, the split into payloadCreator as first arg and the rest of the config as a second arg seems to be necessary, unfortunately) |
Or we go for something like createSlice({
name: 'test',
initialState: {} as TestState,
reducers: withSpecial => ({
testInfer: withSpecial.asyncThunk(
(arg: TestArg, api) => {
return Promise.resolve({ payload: 'foo' } as TestReturned)
},
{
pendingReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
},
fulfilledReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
expectType<TestReturned>(action.payload)
},
rejectedReducer(state, action) {
expectType<TestState>(state)
expectType<TestArg>(action.meta.arg)
expectType<SerializedError>(action.error)
}
}
)
})
}) |
So purely from a type standpoint it looks like that would be possible: (With some hiccups that I'd still need to solve and serious need for refactoring) |
As much as I want this, doesn't seem like it's going to happen due to TS complexity: #637 . |
Here's one that's been asked for a lot since we came up with
createSlice
: adding some kind of syntax for defining thunks directly inside of thecreateSlice
call.Now that I've actually used
createAsyncThunk
a few times in the new Redux tutorial I'm writing, I can see that there's still some pain points there:name
in your action type prefix argextraReducers
and defining the handlers for each resultWe're going to ignore the issue of defining loading state and stuff for now, and focus on what a possible syntax for this might look like.
The biggest complicating factor here is the TS usage.
createAsyncThunk
may require several possible generic args, including{dispatch, state, extra}
. We can't know, at the time the slice is defined, what thestate
type might be.@phryneas listed several possible syntaxes in chat discussion, along with why they won't work. Pasting that here for reference:
However, I noted that Easy-Peasy uses a
thunk()
helper, and after a bit more discussion:I think it's something that's worth pursuing.
The text was updated successfully, but these errors were encountered: