1 | import verifySubselectors from './verifySubselectors'
|
2 |
|
3 | export 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 |
|
18 | export 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 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | export 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 | }
|