Created
August 17, 2015 17:47
-
-
Save tadjik1/f40fed99530df8c79ba6 to your computer and use it in GitHub Desktop.
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 selectn from 'selectn'; | |
import { union } from 'lodash'; | |
/** | |
* list of default fields for all of our lists | |
* @type {{items: Array, isFetching: boolean, lastUpdated: null, didInvalidate: boolean, pagination: {}}} | |
*/ | |
export const defaultFields = { | |
items: [], | |
isFetching: false, | |
lastUpdated: null, | |
didInvalidate: false, | |
pagination: {} | |
}; | |
/** | |
* Helper function that allow to reduce boilerplate when creating initial states for reducers | |
* @param {Array} entityNames - array of needed fields | |
* @returns {Object} initial state for our reducer | |
* | |
* @example | |
* | |
* const initialState = createInitialState(['movies']); | |
* | |
* { | |
* entities: {}, | |
* movies: { | |
* items: [], | |
* isFetching: false, | |
* lastUpdated: null, | |
* didInvalidate: null, | |
* pagination: {} | |
* } | |
* } | |
*/ | |
export const createInitialState = (entityNames = []) => { | |
return Object.assign({entities: {}}, ...entityNames.map(name => ({ | |
[name]: defaultFields | |
}))); | |
}; | |
export const createReducer = (initialState, handlers = { common: state => state }) => { | |
if (!handlers.hasOwnProperty('common')) throw new Error('Expected an \`common\` method.'); | |
return (state = initialState, action) => { | |
const newState = handlers.common(state, action); | |
if (handlers.hasOwnProperty(action.type)) { | |
return handlers[action.type](newState, action); | |
} | |
return newState; | |
}; | |
}; | |
export const mergeIsFetching = (type, isFetching) => state => { | |
return Object.assign({}, state, { | |
[type]: Object.assign({}, state[type], { | |
isFetching | |
}) | |
}); | |
}; | |
export const mergeIntoBag = (entityName, type) => (state, action) => { | |
const ids = selectn(`payload.result.${entityName}`, action) || []; | |
const pagination = selectn('payload.result.meta.pagination', action) || {}; | |
return Object.assign({}, state, { | |
[type]: Object.assign({}, state[type], { | |
isFetching: false, | |
items: union(state[type].items, ids), | |
lastUpdated: Date.now(), | |
pagination | |
}) | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment