/
selectors.js
44 lines (36 loc) · 1.36 KB
/
selectors.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { matchPath } from "react-router"
const createSelectors = (structure) => {
const { getIn, toJS } = structure
const isRouter = (value) => value != null &&
typeof value === 'object' &&
getIn(value, ['location']) &&
getIn(value, ['action'])
const getRouter = state => {
const router = toJS(getIn(state, ['router']))
if (!isRouter(router)) { throw 'Could not find router reducer in state tree, it must be mounted under "router"' }
return router
}
const getLocation = state => toJS(getIn(getRouter(state), ['location']))
const getAction = state => toJS(getIn(getRouter(state), ['action']))
// It only makes sense to recalculate the `matchPath` whenever the pathname
// of the location changes. That's why `createMatchSelector` memoizes
// the latest result based on the location's pathname.
const createMatchSelector = path => {
let lastPathname = null
let lastMatch = null
return state => {
const { pathname } = getLocation(state) || {}
if (pathname === lastPathname) {
return lastMatch
}
lastPathname = pathname
const match = matchPath(pathname, path)
if (!match || !lastMatch || match.url !== lastMatch.url) {
lastMatch = match
}
return lastMatch
}
}
return {getLocation, getAction, getRouter, createMatchSelector}
}
export default createSelectors