Last active
September 23, 2016 17:21
-
-
Save atticoos/3c266700a42728e21d12ebf9605f5915 to your computer and use it in GitHub Desktop.
Asynchronous action middleware example for Redux
This file contains hidden or 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
const Status = { | |
REQUEST: 'requrest', | |
SUCCESS: 'success', | |
FAILURE: 'failure' | |
}; | |
function requestAction (payload, type) { | |
return { | |
...payload, | |
status: Status.REQUEST, | |
type | |
}; | |
} | |
function failureAction (payload, type, error) { | |
return { | |
...payload, | |
status: Status.FAILURE, | |
type, | |
error | |
} | |
} | |
function successAction (payload, type, response) { | |
return { | |
...payload, | |
status: Status.SUCCESS, | |
type, | |
response | |
}; | |
} | |
export default function callAPI ({dispatch, getState}) { | |
return next => action => { | |
const { | |
type, | |
callAPI, | |
shouldCallAPI = () => true, | |
payload = {}, | |
} = action; | |
if (typeof callAPI !== 'function') { | |
return next(action); | |
} | |
if (!shouldCallAPI(getState()) { | |
return Promise.reject(new Error('Skipped')); | |
} | |
// dispatch an action for the `request` stage. | |
dispatch(requestAction(payload, type)); | |
// Return the promise from the async method, which halts the middleware from going further (`next` is not called). | |
// When the promise completes, we create a new dispatched message with the outcome. | |
return callAPI(getState()) | |
.then(response => dispatch(successAction(payload, type, response))) | |
.catch(error => dispatch(failureAction(payload, type, error))); | |
} | |
} |
This file contains hidden or 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 function someAsyncAction (someId) { | |
return { | |
type: SOME_ASYNC_ACTION, | |
callAPI: () => api.somePromiseMethod(someId), | |
payload: {someId} | |
}; | |
} | |
// results in: | |
// { | |
// type: SOME_ASYNC_ACTION, | |
// status: 'request', | |
// payload: {someId: 1234} | |
// } | |
// and then if successful: | |
// { | |
// type: SOME_ASYNC_ACTION, | |
// status: 'success', | |
// payload: {someId: 1234}, | |
// response: {foo: 'bar', id: 1234} | |
// } | |
// or if unsuccessful: | |
// { | |
// type: SOME_ASYNC_ACTION, | |
// status: 'failure', | |
// payload: someId: 1234}, | |
// error: {statusCode: 404, message: 'Record not found'} | |
// } |
This file contains hidden or 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 default function someReducer (state = {}, action) { | |
switch (action) { | |
case SOME_ASYNC_ACTION: | |
switch (action.status) { | |
case Status.REUQEST: | |
return { | |
...state, | |
loading: true | |
}; | |
case Status.SUCCESS: | |
return { | |
...state, | |
[action.someId]: action.response, | |
loading: false, | |
error: null | |
}; | |
case Status.FAILURE: | |
return { | |
...state, | |
[action.someId]: null, | |
loading: false, | |
error: action.error | |
}; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment