Skip to content

Instantly share code, notes, and snippets.

@mnazim
Created December 14, 2015 21:06
Show Gist options
  • Save mnazim/33c7739c62a5877f0aa7 to your computer and use it in GitHub Desktop.
Save mnazim/33c7739c62a5877f0aa7 to your computer and use it in GitHub Desktop.
import { Schema, arrayOf, normalize } from 'normalizr';
import { camelizeKeys } from 'humps';
import axios from 'axios';
const API_ROOT = 'http://localhost:5555/api/v1/';
// Fetches an API response.
// This makes every API response have the same shape, regardless of how nested it was.
function callApi(endpoint, method = 'get', data = {}, schema = null) {
const fullUrl = (endpoint.indexOf(API_ROOT) === -1) ? API_ROOT + endpoint : endpoint;
if (method.toLowerCase() == 'get') {
return axios.get(
fullUrl,
{ params: data }
);
}
else {
return axios.post(
fullUrl,
data
);
}
}
// Action key that carries API call info interpreted by this Redux middleware.
export const CALL_API = Symbol('Call API');
// A Redux middleware that interprets actions with CALL_API info specified.
// Performs the call and promises when such actions are dispatched.
export default store => next => action => {
const callAPI = action[CALL_API];
if (typeof callAPI === 'undefined') {
return next(action);
}
let { endpoint } = callAPI;
const { schema, types, method, data } = callAPI;
if (typeof endpoint === 'function') {
endpoint = endpoint(store.getState());
}
if (typeof endpoint !== 'string') {
throw new Error('Specify a string endpoint URL.');
}
if (!Array.isArray(types) || types.length !== 3) {
throw new Error('Expected an array of three action types.');
}
if (!types.every(type => typeof type === 'string')) {
throw new Error('Expected action types to be strings.');
}
function actionWith(data) {
const finalAction = Object.assign({}, action, data);
delete finalAction[CALL_API];
return finalAction;
}
const [requestType, successType, failureType] = types;
next(actionWith({ type: requestType }));
return callApi(endpoint, method, data, schema).then(
response => next(actionWith({
response,
type: successType
})),
error => next(actionWith({
type: failureType,
error: error.message || 'Something went wrong!'
}))
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment