Skip to content

Commit a1d4091

Browse files
committed
Rework dispatched thunk action contents
- Move args inside `meta` - Include contents directly as `payload`
1 parent 58df106 commit a1d4091

File tree

2 files changed

+47
-28
lines changed

2 files changed

+47
-28
lines changed

src/createAsyncThunk.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ describe('createAsyncThunk', () => {
44
it('creates the action types', () => {
55
const thunkActionCreator = createAsyncThunk('testType', async () => 42)
66

7-
expect(thunkActionCreator.fulfilled.type).toBe('testType')
7+
expect(thunkActionCreator.fulfilled.type).toBe('testType/fulfilled')
88
expect(thunkActionCreator.pending.type).toBe('testType/pending')
99
expect(thunkActionCreator.finished.type).toBe('testType/finished')
1010
expect(thunkActionCreator.rejected.type).toBe('testType/rejected')
@@ -34,17 +34,17 @@ describe('createAsyncThunk', () => {
3434

3535
expect(dispatch).toHaveBeenNthCalledWith(
3636
1,
37-
thunkActionCreator.pending({ args })
37+
thunkActionCreator.pending(args)
3838
)
3939

4040
expect(dispatch).toHaveBeenNthCalledWith(
4141
2,
42-
thunkActionCreator.fulfilled({ args, result })
42+
thunkActionCreator.fulfilled(result, args)
4343
)
4444

4545
expect(dispatch).toHaveBeenNthCalledWith(
4646
3,
47-
thunkActionCreator.finished({ args })
47+
thunkActionCreator.finished(args)
4848
)
4949
})
5050

@@ -66,17 +66,17 @@ describe('createAsyncThunk', () => {
6666

6767
expect(dispatch).toHaveBeenNthCalledWith(
6868
1,
69-
thunkActionCreator.pending({ args })
69+
thunkActionCreator.pending(args)
7070
)
7171

7272
expect(dispatch).toHaveBeenNthCalledWith(
7373
2,
74-
thunkActionCreator.rejected({ args, error })
74+
thunkActionCreator.rejected(error, args)
7575
)
7676

7777
expect(dispatch).toHaveBeenNthCalledWith(
7878
3,
79-
thunkActionCreator.finished({ args })
79+
thunkActionCreator.finished(args)
8080
)
8181
})
8282
})

src/createAsyncThunk.ts

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Dispatch } from 'redux'
2-
import { ActionCreatorWithPayload, createAction } from './createAction'
2+
import { createAction } from './createAction'
33

44
export type Await<T> = T extends {
55
then(onfulfilled?: (value: infer U) => unknown): unknown
@@ -42,45 +42,64 @@ export function createAsyncThunk<
4242
undefined
4343
>
4444
>(type: ActionType, payloadCreator: PayloadCreator) {
45+
// TODO This results in some hideous-looking inferred types for the actions
4546
type ActionParams = Parameters<PayloadCreator>[0]['args']
4647

47-
const fulfilled = createAction(type) as ActionCreatorWithPayload<
48-
{ args: ActionParams; result: Await<ReturnType<PayloadCreator>> },
49-
ActionType
50-
>
48+
const fulfilled = createAction(
49+
type + '/fulfilled',
50+
(result: Await<ReturnType<PayloadCreator>>, args: ActionParams) => {
51+
return {
52+
payload: result,
53+
meta: { args }
54+
}
55+
}
56+
)
5157

52-
const pending = createAction(type + '/pending') as ActionCreatorWithPayload<
53-
{ args: ActionParams },
54-
string
55-
>
58+
const pending = createAction(type + '/pending', (args: ActionParams) => {
59+
return {
60+
payload: undefined,
61+
meta: { args }
62+
}
63+
})
5664

57-
const finished = createAction(type + '/finished') as ActionCreatorWithPayload<
58-
{ args: ActionParams },
59-
string
60-
>
65+
const finished = createAction(type + '/finished', (args: ActionParams) => {
66+
return {
67+
payload: undefined,
68+
meta: { args }
69+
}
70+
})
6171

62-
const rejected = createAction(type + '/rejected') as ActionCreatorWithPayload<
63-
{ args: ActionParams; error: Error },
64-
string
65-
>
72+
const rejected = createAction(
73+
type + '/rejected',
74+
(error: Error, args: ActionParams) => {
75+
return {
76+
payload: undefined,
77+
error,
78+
meta: { args }
79+
}
80+
}
81+
)
6682

6783
function actionCreator(args?: ActionParams) {
6884
return async (dispatch: any, getState: any, extra: any) => {
6985
try {
70-
dispatch(pending({ args }))
86+
dispatch(pending(args))
87+
// TODO Also ugly types
7188
const result: Await<ReturnType<PayloadCreator>> = await payloadCreator({
7289
args,
7390
dispatch,
7491
getState,
7592
extra
7693
})
94+
7795
// TODO How do we avoid errors in here from hitting the catch clause?
78-
return dispatch(fulfilled({ args, result }))
96+
return dispatch(fulfilled(result, args))
7997
} catch (err) {
8098
// TODO Errors aren't serializable
81-
dispatch(rejected({ args, error: err }))
99+
dispatch(rejected(err, args))
82100
} finally {
83-
dispatch(finished({ args }))
101+
// TODO IS there really a benefit from a "finished" action?
102+
dispatch(finished(args))
84103
}
85104
}
86105
}

0 commit comments

Comments
 (0)