src/index.js
import { CALL_API } from 'redux-api-middleware';
import {
createPendingType,
createSuccessType,
createFailureType,
createDefaultBailout,
extendAction
} from './util-action';
import { fetchSuccess, fetchFailure, fetchPending } from './util-reducer';
/**
* creates action for data fetching
* @param {string} [id] - identifier for the action
* @param {string} [url] - url to fetch
* @param {object} [options] - options to consider when creating action
* @param {object|function} [meta] - an object with data to put in the FSA
action or a function to calculate it
with the following signature:
(action, state, response) -> object
* @returns {object} - redux-api-middleware compatible action
*/
export function createFetchAction(id, url, options = {}, meta = {}) {
if (!id || !url) {
throw new Error('Must provide action identifier and url');
}
let metaFunction;
if (typeof meta === 'function') {
metaFunction = meta;
} else {
metaFunction = () => meta;
}
const defaults = {
force: false,
method: 'GET',
body: ''
};
const settings = {
...defaults,
...options
};
const actionPrefix = id.toUpperCase();
const bailout = settings.bailout || createDefaultBailout(id, settings.force);
const baseAction = {
endpoint: url,
bailout,
method: settings.method,
types: [
createPendingType(actionPrefix, url, metaFunction),
createSuccessType(actionPrefix, url, metaFunction),
createFailureType(actionPrefix, url, metaFunction)
]
};
const middlewareAction = {
[CALL_API]: extendAction(baseAction, settings)
};
return middlewareAction;
}
/**
* creates reducer for data fetching
* @param {string} [id] - identifier that the corresponding action uses
* @returns {object} - redux-api-middleware compatible action
*/
export function createFetchReducer(id) {
if (!id) {
throw new Error('Must provide action identifier for reducer');
}
const actionPrefix = id.toUpperCase();
return (state = {}, { type, payload, meta, error }) => {
if (type === actionPrefix + '_FETCH_SUCCESS') {
return fetchSuccess(payload, meta);
}
if (type === actionPrefix + '_FETCH_FAILURE') {
return fetchFailure(payload, meta);
}
if (type === actionPrefix + '_FETCH_PENDING') {
return fetchPending(payload, meta, error);
}
return state;
};
}