bdn-pocket
Version:
pocket tools for managing redux and redux-saga
65 lines (57 loc) • 2.03 kB
JavaScript
import stampit from '@stamp/it'
import equals from 'ramda/src/equals'
import pathOr from 'ramda/src/pathOr'
import propOr from 'ramda/src/propOr'
import MakeReqMessenger from '../messenger/make_req_messenger'
import SelectorDef, { makeIsCacheValid } from './selector_def'
const Selector = stampit(SelectorDef)
.methods({
getPag(pags, id) {
const { defaultState } = MakeReqMessenger.compose.deepProperties
if (pags === undefined) {
throw new Error(`
pags parameter is undefined -
expected an object indexed by id
`)
}
const getter = Array.isArray(id) ? pathOr : propOr
return getter(defaultState, id, pags)
}
})
.init(({ reducer }, { stamp, instance }) => {
const { PropTypes } = stamp.compose.staticProperties
const {
getSubState,
} = instance
const isPropsCacheValid = makeIsCacheValid(equals)
const boundReducer = reducer.bind(instance)
const isSubStateCacheValid = makeIsCacheValid((r, l) => r === l)
let lastResult
let lastPartialReducer
/**
* propsReducer generate a partial reducer function
* that is memoized (lastPartialReducer)
* if props is sent, propsReducer execute the partial reducer
* else it return the partial reducer
*/
return function propsReducer(state, props) {
const subStates = getSubState(state)
// memoize partial reducer
// this partial reducer will be reused in next call if args remains equal
if (!isSubStateCacheValid(subStates)) {
// invalidate props cache to ensure reducer to run next time
isPropsCacheValid(undefined)
lastPartialReducer = (props = {}) => {
PropTypes(props)
if ( !isPropsCacheValid(props) ) {
lastResult = boundReducer(subStates, props, { instance })
}
return lastResult
}
}
return props === undefined ?
lastPartialReducer :
lastPartialReducer(props)
}
})
export default Selector