Skip to content

Instantly share code, notes, and snippets.

@atticoos
Last active September 23, 2016 17:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atticoos/3c266700a42728e21d12ebf9605f5915 to your computer and use it in GitHub Desktop.
Save atticoos/3c266700a42728e21d12ebf9605f5915 to your computer and use it in GitHub Desktop.
Asynchronous action middleware example for Redux
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)));
}
}
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'}
// }
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