Last active
September 10, 2020 03:20
-
-
Save jonjaques/ccca52fd73f24bd90f7ac3d1d53a6e26 to your computer and use it in GitHub Desktop.
Create Async Actions w/ Redux-Toolkit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const fetchStuff = createAsyncAction('fetchStuff', (id) => api.fetch(id)) | |
export interface IState { | |
loading: boolean | |
stuff?: IStuff | |
error?: Error | |
} | |
export default createReducer<IState>({loading: false}, builder => builder | |
.addCase(fetchStuff.pending, (state, action) => { | |
state.loading = true | |
}) | |
.addCase(fetchStuff.fulfilled, (state, action) => { | |
// action.payload.args === id | |
state.stuff = action.payload.result | |
}) | |
.addCase(fetchStuff.rejected, (state, action) => { | |
state.error = action.payload.result | |
delete state.stuff | |
}) | |
.addCase(fetchStuff.finished, (state, action) => { | |
state.loading = false | |
}) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
ActionCreatorWithPayload, | |
createAction, | |
Dispatch, | |
} from '@reduxjs/toolkit' | |
export type Await<T> = T extends { | |
then(onfulfilled?: (value: infer U) => unknown): unknown | |
} | |
? U | |
: T | |
export type AsyncActionCreator< | |
A, | |
D extends Dispatch, | |
S extends any, | |
E extends any | |
> = (args: A, dispatch: D, getState: () => S, extra: E) => any | |
export function createAsyncAction< | |
ActionType extends string, | |
PayloadCreator extends AsyncActionCreator<any, Dispatch, any, undefined> | |
>(type: ActionType, payloadCreator: PayloadCreator) { | |
type ActionParams = Parameters<PayloadCreator>[0] | |
const fulfilled = createAction(type) as ActionCreatorWithPayload< | |
{ args: ActionParams; result: Await<ReturnType<PayloadCreator>> }, | |
ActionType | |
> | |
const pending = createAction(type + '_PENDING') as ActionCreatorWithPayload< | |
{ args: ActionParams }, | |
string | |
> | |
const finished = createAction(type + '_FINISHED') as ActionCreatorWithPayload< | |
{ args: ActionParams }, | |
string | |
> | |
const rejected = createAction(type + '_REJECTED') as ActionCreatorWithPayload< | |
{ args: ActionParams; error: Error }, | |
string | |
> | |
function actionCreator(args?: ActionParams) { | |
return async (dispatch: any, getState: any, extra: any) => { | |
try { | |
dispatch(pending({ args })) | |
const result: Await<ReturnType<PayloadCreator>> = await payloadCreator( | |
args, | |
dispatch, | |
getState, | |
extra | |
) | |
return dispatch(fulfilled({ args, result })) | |
} catch (err) { | |
dispatch(rejected({ args, error: err })) | |
} finally { | |
dispatch(finished({ args }) | |
} | |
} | |
} | |
actionCreator.pending = pending | |
actionCreator.rejected = rejected | |
actionCreator.fulfilled = fulfilled | |
actionCreator.finished = finished | |
return actionCreator | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment