Installations
npm install reselect-mapper
Developer Guide
Typescript
No
Module System
CommonJS
Min. Node Version
>=10
Node Version
14.8.0
NPM Version
6.14.7
Score
68.8
Supply Chain
98.7
Quality
74.5
Maintenance
25
Vulnerability
100
License
Releases
Unable to fetch releases
Contributors
Unable to fetch Contributors
Languages
TypeScript (93.98%)
HTML (6.02%)
Love this project? Help keep it running — sponsor us today! 🚀
Developer
fernandoem88
Download Statistics
Total Downloads
384
Last Day
1
Last Week
2
Last Month
12
Last Year
50
GitHub Statistics
3 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Feb 17, 2021
Package Meta Information
Latest Version
1.0.1
Package Id
reselect-mapper@1.0.1
Unpacked Size
64.72 kB
Size
11.97 kB
File Count
19
NPM Version
6.14.7
Node Version
14.8.0
Total Downloads
Cumulative downloads
Total Downloads
384
Last Day
0%
1
Compared to previous day
Last Week
100%
2
Compared to previous week
Last Month
200%
12
Compared to previous month
Last Year
-15.3%
50
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Peer Dependencies
4
Dev Dependencies
32
reselect-mapper
this is a small package that will help us to define and use your selectors in a clean, easy and fast way.
more specifically it will help us to
- define all our selectors in a linear way
- one and only one way to combine selecotrs
- use named selector hooks to avoid importing a lot of selectors in a file and have a fast access to all our selectors.
Install
1npm install --save reselect-mapper
Package content
Here are what we can import from the package
- mapSelectors
- createParamsSelectorHook
- createNamedSelectorHook,
1import { 2 mapSelectors, 3 createParamsSelectorHook, 4 createNamedSelectorHook 5} from 'reselect-mapper'
mapSelectors
this helper uses createSelector from reselect and brings out 2 main benefits
- a simple way to combine selectors using records
1import { mapSelectors } from 'reselect-mapper' 2 3const getMin = (state: State) => state.min 4const getMax = (state: State) => state.max 5// now if we want to get the difference between the max and the min, 6// taking account of the state offset, we can proceed like this 7const getOffsetDiff = mapSelectors( 8 // selectors are passed using a record, 9 // so the mapping is done directly here 10 { min: getMin, max: getMax }, 11 ( 12 map, // map signature is { min: number, max: number }, => low risk to have typos when accessing selected value 13 state: State 14 ) => state.offset + map.max - map.min 15)
- no extra efforts needed when combining selectors with params: the synthax does not change
1const getUserById = (state: State, id: string) => state.users[id] 2const getPostByIndex = (state: State, index: number) => state.posts[index] 3 4const getUserAndPost = mapSelectors( 5 { user: getUserById, post: getPostByIndex }, 6 (map) => map // map here is { user: User, post: Post } 7)
instead if we used createSelector from reselect package, the synthax would be a curry function and a bit complex
1const getUserById = (id: string) => (state: State) => state.users[id]
2const getPostByIndex = (index: number) => (state: State) => state.posts[index]
3
4const getUserAndPost = (id: string, index: number) =>
5 // curry function
6 createSelector(
7 // selectors are passed in an array and should not be curry functions
8 [
9 // so we need to pass all the parameters again here
10 getUserById(id),
11 getPostByIndex(index)
12 ],
13 // the mapping is done in the callback params
14 // => high risk of introducing bad mapping while dealing with a lot of selectors:
15 // => we can easily define (post, user) => any instead of (user, post) => any
16 (user, post) => ({
17 user,
18 post
19 })
20 )
let's now have a look to this selectors.ts file example to see how it will look like in a real project
1import { mapSelectors } from 'reselect-mapper' 2type State = { 3 group: string 4 creationDate: string 5 users: { [K: string]: User } 6 posts: { [K: number]: Post } 7} 8// no params selector 9export const getGroup = (state: State) => state.group 10export const getCreationDate = (state: State) => state.creationDate 11// selector with params 12export const getUserById = (state: State, id: string) => state.users[id] 13export const getPostByIndex = (state: State, index: number) => state.posts[index] 14// combining no params selectors 15export const getGroupAndCreationDate = mapSelectors( 16 // selectors record 17 { group: getGroup, date: getCreationDate }, 18 (map) => map // map signature is { group: string, date: string } 19) 20// this will return the following selector 21// (state: State) => { group: string, date: string } 22 23// mixing selectors where some of them require params: same synthax as before 24export const getUserAndGroup = mapSelectors( 25 { user: getUserById, group: getGroup, }, 26 (map) => map // map signature is { user: User, group: string } 27) 28// this will return the following selector 29// (state: State, params: { user: string }) => { user: User, group: string } 30 31// here you can notice that, the params is a record and has only one key 32// "user" which is what will be passed to getUserById selector. 33 34// combining selectors where all of them require params: again same synthax 35export const getUserAndPost = mapSelectors( 36 { user: getUserById, post: getPostByIndex }, 37 (map) => map // map signature is { user: User, post: post } 38) 39// this will return the following selector 40// (state: State, params: { user: string, post: number }) 41// => { user: User, post: Post } 42 43// here instead, we passed 2 selectors and the params record has also 2 keys 44// "user": parameter to be passed to getUserById selector 45// "post": parameter to be passed to getPostByIndex selector 46}
now we we can use these selectors in our component MyComponent.tsx let's first try to use useSelector from react-redux
1import { useSelector } from 'react-redux' 2 3import { 4 getGroup, 5 getUserById, 6 getCreationDate, 7 getGroupAndCreationDate, 8 getUserAndGroup, 9 getUserAndPost 10} from './selectors' 11 12const MyComponent = () => { 13 // how to use a no params selector 14 const group = useSelector(getGroup) 15 const date = useSelector(getCreationDate) 16 // how to use a no params combined selector 17 const groupAndDate = useSelector(getGroupAndCreationDate) 18 // how to use a selector with params 19 const user = useSelector((state) => getUserById(state, 'userId')) 20 const userAndGroup = useSelector((state) => 21 getUserAndGroup(state, { user: 'userId' }) 22 ) 23 const userAndPost = useSelector((state) => 24 getUserAndPost(state, { 25 user: 'userId', 26 post: 3 27 }) 28 ) 29 return <div>test</div> 30}
createParamsSelectorHook
as we could notice, when it comes to pass parameters to the selector using the standard useSelector from redux, we have to use a curry function. but we can remove it by creating a params selector hook
creating a params selector hook using store
1import { createStore } from 'redux' 2import reducers, { initialState } from './reducers' 3import { createParamsSelectorHook } from 'reselect-mapper' 4 5const store = createStore(reducers, initialState) 6const useSelector = createParamsSelectorHook(store) 7 8// now we can use it like this 9const value1 = useSelector(selectorWithNoParams) 10const value2 = useSelector(selectorWithParams, params)
creating a params selector hook using useSelector hook
1import { useSelector as useDefaultSelector } from 'react-redux' 2import { createParamsSelectorHook } from 'reselect-mapper' 3 4const useSelector = createParamsSelectorHook(useDefaultSelector) 5 6// now we can use it like follows 7const value1 = useSelector(selectorWithNoParams) 8const value2 = useSelector(selectorWithParams, params)
createNamedSelectorHook
in the previous example we saw how to use our selectors but one thing we can notice is that we had to import all the desired selectors in our component file. And this is an operation we will often do. That means, we should deal many times with the following situations:
-
repetitive imports: we are importing the same selector functions many times in different files => more line of codes => more file size
-
conflicting selectors: let's imagine we have both getX and getY from ./pippo/selectors.ts and ./pluto/selectors.ts. it can happen to import the wrong getX or the wrong getY due to the multiple imports we can have in our file. But more often, we'll have to import both of them in the same file, and in this case, to avoid conflictual imports, we need to rename all those selectors like follows:
1import { getX as getPippoX, getY as getPippoY } from '/pippo/selectors' 2import { getX as getPlutoX, getY as getPlutoY } from '/pluto/selectors'
these situations are not a big deal, but since they will come over and over in our daily work, using a named selector hook will eventually have a global impact at the end of the day because it will help us to have a clean file with less imports, to avoid selectors conflict and have a fast access to all our selectors.
so let's then define a hooks.ts file where we can create our a named selector hook and see how to use it
we need the selectors records and either the store or the default useSelector to create named hooks
1import { createNamedSelectorHook } from 'reselect-mapper' 2import { useSelector, shallowEqual, createSelectorHook } from 'react-redux' 3import { store } from './configs' 4import * as userSelectors from './selectors' 5 6// creating useUserSelectors from store 7export const useUserSelectors = createNamedSelectorHook(store)(userSelectors) 8 9// creating useUserSelectors from useSelector 10export const useUserSelectorsShallEq = createNamedSelectorHook(useSelector)( 11 userSelectors 12) 13 14const useShallowEqualSelector = (selector: Selector) => 15 useSelector(selector, shallowEqual) 16// creating useUserSelectors from useShallowEqualSelector 17export const useUserSelectorsShallEq = createNamedSelectorHook( 18 useShallowEqualSelector 19)(userSelectors) 20 21const useSelectorInSomeContext = createSelectorHook(myContext) 22// creating useUserSelectors from useSelectorInSomeContext 23export const useUserSelectorsInContext = createNamedSelectorHook( 24 useSelectorInSomeContext 25)(userSelectors)
now we defined the useUserSelectors, we can change the MyComponent.tsx file removing all the imported selectors, import only our named hook and use it instead of useSelector
1// we have only 1 import here instead of 7 2import { useUserSelectors } from './hooks' 3// import { useSelector } from 'reselect-mapper' 4/*import { 5 getGroup, 6 getUserById, 7 getCreationDate, 8 getGroupAndCreationDate, 9 getUserAndGroup, 10 getUserAndPost 11 } from './selectors' 12 */ 13 14const MyComponent = () => { 15 // how to use a no params selector 16 const group = useUserSelectors('getGroup') 17 const date = useUserSelectors('getCreationDate') 18 // how to use a no params combined selector 19 const groupAndDate = useUserSelectors('getGroupAndCreationDate') 20 // how to use a selector with params 21 const user = useUserSelectors('getUserById', 'userId') 22 const userAndGroup = useUserSelectors('getUserAndGroup', { user: 'userId' }) 23 const userAndPost = useUserSelectors('getUserAndPost', { 24 user: 'userId', 25 post: 3 26 }) 27 return <div>test</div> 28}
Also here, the named selector hook accepts 1 or 2 arguments.
- the selector name: first and required argument, a string reference of a desired selector
- the selector's parameter: required if the given selector from the selector name requires a parameter
as you can see, in this case, we directly also avoid selectors names conflicts
1// import { getX as getPippoX, getY as getPippoY } from '/pippo/selectors' 2// import { getX as getPlutoX, getY as getPlutoY } from '/pluto/selectors' 3import { usePippoSelectors } from '/pippo/hooks' 4import { usePlutoSelectors } from '/pluto/hooks' 5 6const MyComponent = () => { 7 const pippoX = usePippoSelectors('getX') 8 const plutoX = usePlutoSelectors('getX') 9 return <div>test</div> 10}
try it out! see this code sandbox example
see also
License
MIT © https://github.com/fernandoem88/react-context-selector

No vulnerabilities found.
Reason
no binaries found in the repo
Reason
Found 0/3 approved changesets -- score normalized to 0
Reason
no SAST tool detected
Details
- Warn: no pull requests merged into dev branch
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
license file not detected
Details
- Warn: project does not have a license file
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
84 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-whgm-jr23-g3j9
- Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw
- Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25
- Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw
- Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5
- Warn: Project is vulnerable to: GHSA-257v-vj4p-3w2h
- Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq
- Warn: Project is vulnerable to: GHSA-3wcq-x3mq-6r9p
- Warn: Project is vulnerable to: GHSA-434g-2637-qmqr
- Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m
- Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw
- Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p
- Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747
- Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh
- Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h
- Warn: Project is vulnerable to: GHSA-6h5x-7c5m-7cr7
- Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc
- Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx
- Warn: Project is vulnerable to: GHSA-74fj-2j2h-c42q
- Warn: Project is vulnerable to: GHSA-pw2r-vq6v-hr8c
- Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc
- Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp
- Warn: Project is vulnerable to: GHSA-8mmm-9v2q-x3f9
- Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6
- Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj
- Warn: Project is vulnerable to: GHSA-c7qv-q95q-8v27
- Warn: Project is vulnerable to: GHSA-33f9-j839-rf8h
- Warn: Project is vulnerable to: GHSA-c36v-fmgq-m8hx
- Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22
- Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp
- Warn: Project is vulnerable to: GHSA-7r28-3m3f-r2pr
- Warn: Project is vulnerable to: GHSA-r8j5-h5cx-65gg
- Warn: Project is vulnerable to: GHSA-896r-f27r-55mw
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq
- Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488
- Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g
- Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9
- Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h
- Warn: Project is vulnerable to: GHSA-5rrq-pxf6-6jx5
- Warn: Project is vulnerable to: GHSA-8fr3-hfg3-gpgp
- Warn: Project is vulnerable to: GHSA-gf8q-jrpm-jvxq
- Warn: Project is vulnerable to: GHSA-2r2c-g63r-vccr
- Warn: Project is vulnerable to: GHSA-cfm4-qjh2-4765
- Warn: Project is vulnerable to: GHSA-x4jg-mjrx-434g
- Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p
- Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr
- Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9
- Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j
- Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w
- Warn: Project is vulnerable to: GHSA-566m-qj78-rww5
- Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j
- Warn: Project is vulnerable to: GHSA-hwj9-h5mp-3pm3
- Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp
- Warn: Project is vulnerable to: GHSA-5q6m-3h65-w53x
- Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg
- Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5
- Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p
- Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7
- Warn: Project is vulnerable to: GHSA-vx3p-948g-6vhq
- Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc
- Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v
- Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3
- Warn: Project is vulnerable to: GHSA-9m6j-fcg5-2442
- Warn: Project is vulnerable to: GHSA-hh27-ffr2-f2jc
- Warn: Project is vulnerable to: GHSA-rqff-837h-mm52
- Warn: Project is vulnerable to: GHSA-8v38-pw62-9cw2
- Warn: Project is vulnerable to: GHSA-hgjh-723h-mx2j
- Warn: Project is vulnerable to: GHSA-jf5r-8hm2-f872
- Warn: Project is vulnerable to: GHSA-wr3j-pwj9-hqq6
- Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7
- Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Score
1.3
/10
Last Scanned on 2025-02-17
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More