UNPKG

3.79 kBJavaScriptView Raw
1import verifySubselectors from './verifySubselectors'
2
3export function impureFinalPropsSelectorFactory(
4 mapStateToProps,
5 mapDispatchToProps,
6 mergeProps,
7 dispatch
8) {
9 return function impureFinalPropsSelector(state, ownProps) {
10 return mergeProps(
11 mapStateToProps(state, ownProps),
12 mapDispatchToProps(dispatch, ownProps),
13 ownProps
14 )
15 }
16}
17
18export function pureFinalPropsSelectorFactory(
19 mapStateToProps,
20 mapDispatchToProps,
21 mergeProps,
22 dispatch,
23 { areStatesEqual, areOwnPropsEqual, areStatePropsEqual }
24) {
25 let hasRunAtLeastOnce = false
26 let state
27 let ownProps
28 let stateProps
29 let dispatchProps
30 let mergedProps
31
32 function handleFirstCall(firstState, firstOwnProps) {
33 state = firstState
34 ownProps = firstOwnProps
35 stateProps = mapStateToProps(state, ownProps)
36 dispatchProps = mapDispatchToProps(dispatch, ownProps)
37 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
38 hasRunAtLeastOnce = true
39 return mergedProps
40 }
41
42 function handleNewPropsAndNewState() {
43 stateProps = mapStateToProps(state, ownProps)
44
45 if (mapDispatchToProps.dependsOnOwnProps)
46 dispatchProps = mapDispatchToProps(dispatch, ownProps)
47
48 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
49 return mergedProps
50 }
51
52 function handleNewProps() {
53 if (mapStateToProps.dependsOnOwnProps)
54 stateProps = mapStateToProps(state, ownProps)
55
56 if (mapDispatchToProps.dependsOnOwnProps)
57 dispatchProps = mapDispatchToProps(dispatch, ownProps)
58
59 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
60 return mergedProps
61 }
62
63 function handleNewState() {
64 const nextStateProps = mapStateToProps(state, ownProps)
65 const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps)
66 stateProps = nextStateProps
67
68 if (statePropsChanged)
69 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
70
71 return mergedProps
72 }
73
74 function handleSubsequentCalls(nextState, nextOwnProps) {
75 const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps)
76 const stateChanged = !areStatesEqual(nextState, state)
77 state = nextState
78 ownProps = nextOwnProps
79
80 if (propsChanged && stateChanged) return handleNewPropsAndNewState()
81 if (propsChanged) return handleNewProps()
82 if (stateChanged) return handleNewState()
83 return mergedProps
84 }
85
86 return function pureFinalPropsSelector(nextState, nextOwnProps) {
87 return hasRunAtLeastOnce
88 ? handleSubsequentCalls(nextState, nextOwnProps)
89 : handleFirstCall(nextState, nextOwnProps)
90 }
91}
92
93// TODO: Add more comments
94
95// If pure is true, the selector returned by selectorFactory will memoize its results,
96// allowing connectAdvanced's shouldComponentUpdate to return false if final
97// props have not changed. If false, the selector will always return a new
98// object and shouldComponentUpdate will always return true.
99
100export default function finalPropsSelectorFactory(
101 dispatch,
102 { initMapStateToProps, initMapDispatchToProps, initMergeProps, ...options }
103) {
104 const mapStateToProps = initMapStateToProps(dispatch, options)
105 const mapDispatchToProps = initMapDispatchToProps(dispatch, options)
106 const mergeProps = initMergeProps(dispatch, options)
107
108 if (process.env.NODE_ENV !== 'production') {
109 verifySubselectors(
110 mapStateToProps,
111 mapDispatchToProps,
112 mergeProps,
113 options.displayName
114 )
115 }
116
117 const selectorFactory = options.pure
118 ? pureFinalPropsSelectorFactory
119 : impureFinalPropsSelectorFactory
120
121 return selectorFactory(
122 mapStateToProps,
123 mapDispatchToProps,
124 mergeProps,
125 dispatch,
126 options
127 )
128}