@@ -18,61 +18,32 @@ function getDisplayName(WrappedComponent) {
18
18
return WrappedComponent . displayName || WrappedComponent . name || 'Component'
19
19
}
20
20
21
+ function checkStateShape ( stateProps , dispatch ) {
22
+ invariant (
23
+ isPlainObject ( stateProps ) ,
24
+ '`%sToProps` must return an object. Instead received %s.' ,
25
+ dispatch ? 'mapDispatch' : 'mapState' ,
26
+ stateProps
27
+ )
28
+ return stateProps
29
+ }
30
+
21
31
// Helps track hot reloading.
22
32
let nextVersion = 0
23
33
24
34
export default function connect ( mapStateToProps , mapDispatchToProps , mergeProps , options = { } ) {
25
35
const shouldSubscribe = Boolean ( mapStateToProps )
26
- const finalMapStateToProps = mapStateToProps || defaultMapStateToProps
27
- const finalMapDispatchToProps = isPlainObject ( mapDispatchToProps ) ?
36
+ const mapState = mapStateToProps || defaultMapStateToProps
37
+ const mapDispatch = isPlainObject ( mapDispatchToProps ) ?
28
38
wrapActionCreators ( mapDispatchToProps ) :
29
39
mapDispatchToProps || defaultMapDispatchToProps
40
+
30
41
const finalMergeProps = mergeProps || defaultMergeProps
31
- const doStatePropsDependOnOwnProps = finalMapStateToProps . length !== 1
32
- const doDispatchPropsDependOnOwnProps = finalMapDispatchToProps . length !== 1
33
42
const { pure = true , withRef = false } = options
34
43
35
44
// Helps track hot reloading.
36
45
const version = nextVersion ++
37
46
38
- function computeStateProps ( store , props ) {
39
- const state = store . getState ( )
40
- const stateProps = doStatePropsDependOnOwnProps ?
41
- finalMapStateToProps ( state , props ) :
42
- finalMapStateToProps ( state )
43
-
44
- invariant (
45
- isPlainObject ( stateProps ) ,
46
- '`mapStateToProps` must return an object. Instead received %s.' ,
47
- stateProps
48
- )
49
- return stateProps
50
- }
51
-
52
- function computeDispatchProps ( store , props ) {
53
- const { dispatch } = store
54
- const dispatchProps = doDispatchPropsDependOnOwnProps ?
55
- finalMapDispatchToProps ( dispatch , props ) :
56
- finalMapDispatchToProps ( dispatch )
57
-
58
- invariant (
59
- isPlainObject ( dispatchProps ) ,
60
- '`mapDispatchToProps` must return an object. Instead received %s.' ,
61
- dispatchProps
62
- )
63
- return dispatchProps
64
- }
65
-
66
- function computeMergedProps ( stateProps , dispatchProps , parentProps ) {
67
- const mergedProps = finalMergeProps ( stateProps , dispatchProps , parentProps )
68
- invariant (
69
- isPlainObject ( mergedProps ) ,
70
- '`mergeProps` must return an object. Instead received %s.' ,
71
- mergedProps
72
- )
73
- return mergedProps
74
- }
75
-
76
47
return function wrapWithConnect ( WrappedComponent ) {
77
48
class Connect extends Component {
78
49
shouldComponentUpdate ( ) {
@@ -96,8 +67,57 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
96
67
this . clearCache ( )
97
68
}
98
69
70
+ computeStateProps ( store , props ) {
71
+ if ( ! this . finalMapStateToProps ) {
72
+ return this . configureFinalMapState ( store , props )
73
+ }
74
+ const state = store . getState ( )
75
+ const stateProps = this . doStatePropsDependOnOwnProps ?
76
+ this . finalMapStateToProps ( state , props ) :
77
+ this . finalMapStateToProps ( state )
78
+
79
+ return checkStateShape ( stateProps )
80
+ }
81
+
82
+ configureFinalMapState ( store , props ) {
83
+ const mappedState = mapState ( store . getState ( ) , props )
84
+ const isFactory = typeof mappedState === 'function'
85
+ this . finalMapStateToProps = isFactory ? mappedState : mapState
86
+ this . doStatePropsDependOnOwnProps = this . finalMapStateToProps . length !== 1
87
+ return isFactory ? this . computeStateProps ( store , props ) : checkStateShape ( mappedState )
88
+ }
89
+
90
+ computeDispatchProps ( store , props ) {
91
+ if ( ! this . finalMapDispatchToProps ) {
92
+ return this . configureFinalMapDispatch ( store , props )
93
+ }
94
+ const { dispatch } = store
95
+ const dispatchProps = this . doDispatchPropsDependOnOwnProps ?
96
+ this . finalMapDispatchToProps ( dispatch , props ) :
97
+ this . finalMapDispatchToProps ( dispatch )
98
+ return checkStateShape ( dispatchProps , true )
99
+ }
100
+
101
+ configureFinalMapDispatch ( store , props ) {
102
+ const mappedDispatch = mapDispatch ( store . dispatch , props )
103
+ const isFactory = typeof mappedDispatch === 'function'
104
+ this . finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch
105
+ this . doDispatchPropsDependOnOwnProps = this . finalMapDispatchToProps . length !== 1
106
+ return isFactory ? this . computeDispatchProps ( store , props ) : checkStateShape ( mappedDispatch , true )
107
+ }
108
+
109
+ computeMergedProps ( stateProps , dispatchProps , parentProps ) {
110
+ const mergedProps = finalMergeProps ( stateProps , dispatchProps , parentProps )
111
+ invariant (
112
+ isPlainObject ( mergedProps ) ,
113
+ '`mergeProps` must return an object. Instead received %s.' ,
114
+ mergedProps
115
+ )
116
+ return mergedProps
117
+ }
118
+
99
119
updateStatePropsIfNeeded ( ) {
100
- const nextStateProps = computeStateProps ( this . store , this . props )
120
+ const nextStateProps = this . computeStateProps ( this . store , this . props )
101
121
if ( this . stateProps && shallowEqual ( nextStateProps , this . stateProps ) ) {
102
122
return false
103
123
}
@@ -107,7 +127,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
107
127
}
108
128
109
129
updateDispatchPropsIfNeeded ( ) {
110
- const nextDispatchProps = computeDispatchProps ( this . store , this . props )
130
+ const nextDispatchProps = this . computeDispatchProps ( this . store , this . props )
111
131
if ( this . dispatchProps && shallowEqual ( nextDispatchProps , this . dispatchProps ) ) {
112
132
return false
113
133
}
@@ -116,12 +136,14 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
116
136
return true
117
137
}
118
138
119
- updateMergedProps ( ) {
120
- this . mergedProps = computeMergedProps (
121
- this . stateProps ,
122
- this . dispatchProps ,
123
- this . props
124
- )
139
+ updateMergedPropsIfNeeded ( ) {
140
+ const nextMergedProps = this . computeMergedProps ( this . stateProps , this . dispatchProps , this . props )
141
+ if ( this . mergedProps && shallowEqual ( nextMergedProps , this . mergedProps ) ) {
142
+ return false
143
+ }
144
+
145
+ this . mergedProps = nextMergedProps
146
+ return true
125
147
}
126
148
127
149
isSubscribed ( ) {
@@ -164,6 +186,8 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
164
186
this . haveOwnPropsChanged = true
165
187
this . hasStoreStateChanged = true
166
188
this . renderedElement = null
189
+ this . finalMapDispatchToProps = null
190
+ this . finalMapStateToProps = null
167
191
}
168
192
169
193
handleChange ( ) {
@@ -203,10 +227,10 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
203
227
let shouldUpdateDispatchProps = true
204
228
if ( pure && renderedElement ) {
205
229
shouldUpdateStateProps = hasStoreStateChanged || (
206
- haveOwnPropsChanged && doStatePropsDependOnOwnProps
230
+ haveOwnPropsChanged && this . doStatePropsDependOnOwnProps
207
231
)
208
232
shouldUpdateDispatchProps =
209
- haveOwnPropsChanged && doDispatchPropsDependOnOwnProps
233
+ haveOwnPropsChanged && this . doDispatchPropsDependOnOwnProps
210
234
}
211
235
212
236
let haveStatePropsChanged = false
@@ -224,7 +248,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
224
248
haveDispatchPropsChanged ||
225
249
haveOwnPropsChanged
226
250
) {
227
- this . updateMergedProps ( )
251
+ haveMergedPropsChanged = this . updateMergedPropsIfNeeded ( )
228
252
} else {
229
253
haveMergedPropsChanged = false
230
254
}
0 commit comments