@@ -18,51 +18,33 @@ function getDisplayName(WrappedComponent) {
1818 return WrappedComponent . displayName || WrappedComponent . name || 'Component'
1919}
2020
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+
2131// Helps track hot reloading.
2232let nextVersion = 0
2333
2434export default function connect ( mapStateToProps , mapDispatchToProps , mergeProps , options = { } ) {
2535 const shouldSubscribe = Boolean ( mapStateToProps )
26- const finalMapStateToProps = mapStateToProps || defaultMapStateToProps
27- const finalMapDispatchToProps = isPlainObject ( mapDispatchToProps ) ?
36+ const mapState = mapStateToProps || defaultMapStateToProps
37+ const mapDispatch = isPlainObject ( mapDispatchToProps ) ?
2838 wrapActionCreators ( mapDispatchToProps ) :
2939 mapDispatchToProps || defaultMapDispatchToProps
40+
3041 const finalMergeProps = mergeProps || defaultMergeProps
31- const doStatePropsDependOnOwnProps = finalMapStateToProps . length !== 1
32- const doDispatchPropsDependOnOwnProps = finalMapDispatchToProps . length !== 1
42+ const checkMergedEquals = finalMergeProps !== defaultMergeProps
3343 const { pure = true , withRef = false } = options
3444
3545 // Helps track hot reloading.
3646 const version = nextVersion ++
3747
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-
6648 function computeMergedProps ( stateProps , dispatchProps , parentProps ) {
6749 const mergedProps = finalMergeProps ( stateProps , dispatchProps , parentProps )
6850 invariant (
@@ -96,8 +78,47 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
9678 this . clearCache ( )
9779 }
9880
81+ computeStateProps ( store , props ) {
82+ if ( ! this . finalMapStateToProps ) {
83+ return this . configureFinalMapState ( store , props )
84+ }
85+ const state = store . getState ( )
86+ const stateProps = this . doStatePropsDependOnOwnProps ?
87+ this . finalMapStateToProps ( state , props ) :
88+ this . finalMapStateToProps ( state )
89+
90+ return checkStateShape ( stateProps )
91+ }
92+
93+ configureFinalMapState ( store , props ) {
94+ const mappedState = mapState ( store . getState ( ) , props )
95+ const isFactory = typeof mappedState === 'function'
96+ this . finalMapStateToProps = isFactory ? mappedState : mapState
97+ this . doStatePropsDependOnOwnProps = this . finalMapStateToProps . length !== 1
98+ return isFactory ? this . computeStateProps ( store , props ) : checkStateShape ( mappedState )
99+ }
100+
101+ computeDispatchProps ( store , props ) {
102+ if ( ! this . finalMapDispatchToProps ) {
103+ return this . configureFinalMapDispatch ( store , props )
104+ }
105+ const { dispatch } = store
106+ const dispatchProps = this . doDispatchPropsDependOnOwnProps ?
107+ this . finalMapDispatchToProps ( dispatch , props ) :
108+ this . finalMapDispatchToProps ( dispatch )
109+ return checkStateShape ( dispatchProps , true )
110+ }
111+
112+ configureFinalMapDispatch ( store , props ) {
113+ const mappedDispatch = mapDispatch ( store . dispatch , props )
114+ const isFactory = typeof mappedDispatch === 'function'
115+ this . finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch
116+ this . doDispatchPropsDependOnOwnProps = this . finalMapDispatchToProps . length !== 1
117+ return isFactory ? this . computeDispatchProps ( store , props ) : checkStateShape ( mappedDispatch , true )
118+ }
119+
99120 updateStatePropsIfNeeded ( ) {
100- const nextStateProps = computeStateProps ( this . store , this . props )
121+ const nextStateProps = this . computeStateProps ( this . store , this . props )
101122 if ( this . stateProps && shallowEqual ( nextStateProps , this . stateProps ) ) {
102123 return false
103124 }
@@ -107,7 +128,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
107128 }
108129
109130 updateDispatchPropsIfNeeded ( ) {
110- const nextDispatchProps = computeDispatchProps ( this . store , this . props )
131+ const nextDispatchProps = this . computeDispatchProps ( this . store , this . props )
111132 if ( this . dispatchProps && shallowEqual ( nextDispatchProps , this . dispatchProps ) ) {
112133 return false
113134 }
@@ -116,12 +137,14 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
116137 return true
117138 }
118139
119- updateMergedProps ( ) {
120- this . mergedProps = computeMergedProps (
121- this . stateProps ,
122- this . dispatchProps ,
123- this . props
124- )
140+ updateMergedPropsIfNeeded ( ) {
141+ const nextMergedProps = computeMergedProps ( this . stateProps , this . dispatchProps , this . props )
142+ if ( this . mergedProps && checkMergedEquals && shallowEqual ( nextMergedProps , this . mergedProps ) ) {
143+ return false
144+ }
145+
146+ this . mergedProps = nextMergedProps
147+ return true
125148 }
126149
127150 isSubscribed ( ) {
@@ -164,6 +187,8 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
164187 this . haveOwnPropsChanged = true
165188 this . hasStoreStateChanged = true
166189 this . renderedElement = null
190+ this . finalMapDispatchToProps = null
191+ this . finalMapStateToProps = null
167192 }
168193
169194 handleChange ( ) {
@@ -203,10 +228,10 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
203228 let shouldUpdateDispatchProps = true
204229 if ( pure && renderedElement ) {
205230 shouldUpdateStateProps = hasStoreStateChanged || (
206- haveOwnPropsChanged && doStatePropsDependOnOwnProps
231+ haveOwnPropsChanged && this . doStatePropsDependOnOwnProps
207232 )
208233 shouldUpdateDispatchProps =
209- haveOwnPropsChanged && doDispatchPropsDependOnOwnProps
234+ haveOwnPropsChanged && this . doDispatchPropsDependOnOwnProps
210235 }
211236
212237 let haveStatePropsChanged = false
@@ -224,7 +249,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
224249 haveDispatchPropsChanged ||
225250 haveOwnPropsChanged
226251 ) {
227- this . updateMergedProps ( )
252+ haveMergedPropsChanged = this . updateMergedPropsIfNeeded ( )
228253 } else {
229254 haveMergedPropsChanged = false
230255 }
0 commit comments