define-selectors
v0.1.1
Published
to define selectors ignoring order
Downloads
4
Maintainers
Readme
define-selectors
define-selectors is a solution to this stackoverflow problem. It works based on Reselect and Re-reselect.
Installation
$ npm install define-selectors
Comparison with reselect
reselect:
import { createSelector } from 'reselect'
const inputSelector1 = (state) => state.val1
const inputSelector2 = (state) => state.val2
const someSelector = createSelector([
inputSelector1,
inputSelector2,
], ( val1, val2 ) => {
// expensive calculation
return val1 + val2
})
define-selectors:
import defineSelectors from 'define-selectors'
const inputSelector1 = (state) => state.val1
const inputSelector2 = (state) => state.val2
const { someSelector } = defineSelectors({
someSelector: [[
inputSelector1,
inputSelector2,
], ( val1, val2 ) => {
// expensive calculation
return val1 + val2
}],
})
// equivalent to above
const { someSelector } = defineSelectors({
someSelector: {
inputSelectors: [
inputSelector1,
inputSelector2,
],
resultFunc: ( val1, val2 ) => {
// expensive calculation
return val1 + val2
},
},
})
Usage
import defineSelectors from 'define-selectors'
const selectNav = state => state.nav
const selectPage = state => state.page
const selectFoo = state => state.foo
const { selectNavAndPageAndFoo, selectNavAndPage } = defineSelectors({
selectNavAndPageAndFoo: [
[ 'selectNavAndPage', selectFoo ], // Note! 'selectNavAndPage' must be string type!
(navAndPage, foo) => {
return `${navAndPage}/${foo}`
},
],
selectNavAndPage: [
[ selectNav, selectPage ],
(nav, page) => {
return `${nav}/${page}`
},
],
})
const state = { nav: 'navA', page: 'pageB', foo: 'fooC' }
console.log( selectNavAndPageAndFoo(state) ) // 'navA/pageB/fooC'
API
define-reselect consists in just one method exported as default.
import defineSelectors from 'define-reselect'
defineSelectors( selectors )
selectors
is a object. key: selectorName, value: selectorData pairs
{
selectorName1: selectorData1,
selectorName2: selectorData2,
...
}
selectorData
is a very important here. it is a object or array. selectorData containsinputSelectors
,resultFunc
,resolverFunc
,cacheSize
,customSelectorCreator
.inputSelectors
,resultFunc
are required and the remainings are optional.selectorData(array):
[ inputSelectors, resultFunc, resolverFunc, cacheSize, customSelectorCreator ]
Note these index position. If you want to use customSelectorCreator
but don't want resolverFunc
and cacheSize
try this:
[ inputSelectors, resultFunc, void 0, void 0, customSelectorCreator ]
- selectorData(object)
{
inputSelectors: inputSelectors,
resultFunc: resultFunc,
resolverFunc: resolverFunc,
cacheSize: cacheSize,
customSelectorCreator: customSelectorCreator,
}
- inputSelectors(array): refer Reselect project. To avoid difinition ordering problem, you have to define each selector in the same
selectors
object. When you use the selector in the same selectors as inputSelector, use selectorName as thestring
type. In above example, when selectNavAndPageAndFoo is defined, it recursively go to theselectNavAndPage
selector to define this first.FOUND_CIRCULAR_REFERENCE
error occurs if a circular reference is found. - resultFunc(function): refer Reselect project
- resolverFunc(function): refer Re-reselect project
- cacheSize(number): refer my unmerged PR to reselect
- customSelectorCreator(function): refer Reselect project
Contributing
Happy to PR any of the improvements you're thinking about. Thanks!