@@ -18,51 +18,33 @@ function getDisplayName(WrappedComponent) {
1818return 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 = { } ) {
2535const shouldSubscribe = Boolean ( mapStateToProps )
26- const finalMapStateToProps = mapStateToProps || defaultMapStateToProps
27- const finalMapDispatchToProps = isPlainObject ( mapDispatchToProps ) ?
36+ const mapState = mapStateToProps || defaultMapStateToProps
37+ const mapDispatch = isPlainObject ( mapDispatchToProps ) ?
2838wrapActionCreators ( mapDispatchToProps ) :
2939mapDispatchToProps || defaultMapDispatchToProps
40+
3041const finalMergeProps = mergeProps || defaultMergeProps
31- const doStatePropsDependOnOwnProps = finalMapStateToProps . length !== 1
32- const doDispatchPropsDependOnOwnProps = finalMapDispatchToProps . length !== 1
42+ const checkMergedEquals = finalMergeProps !== defaultMergeProps
3343const { pure= true , withRef= false } = options
3444
3545// Helps track hot reloading.
3646const 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-
6648function computeMergedProps ( stateProps , dispatchProps , parentProps ) {
6749const mergedProps = finalMergeProps ( stateProps , dispatchProps , parentProps )
6850invariant (
@@ -96,8 +78,58 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
9678this . clearCache ( )
9779}
9880
81+ computeStateProps ( store , props ) {
82+ if ( ! this . finalMapStateToProps ) {
83+ return this . configureFinalMapState ( store , props )
84+ }
85+
86+ const state = store . getState ( )
87+ const stateProps = this . doStatePropsDependOnOwnProps ?
88+ this . finalMapStateToProps ( state , props ) :
89+ this . finalMapStateToProps ( state )
90+
91+ return checkStateShape ( stateProps )
92+ }
93+
94+ configureFinalMapState ( store , props ) {
95+ const mappedState = mapState ( store . getState ( ) , props )
96+ const isFactory = typeof mappedState === 'function'
97+
98+ this . finalMapStateToProps = isFactory ?mappedState :mapState
99+ this . doStatePropsDependOnOwnProps = this . finalMapStateToProps . length !== 1
100+
101+ return isFactory ?
102+ this . computeStateProps ( store , props ) :
103+ checkStateShape ( mappedState )
104+ }
105+
106+ computeDispatchProps ( store , props ) {
107+ if ( ! this . finalMapDispatchToProps ) {
108+ return this . configureFinalMapDispatch ( store , props )
109+ }
110+
111+ const { dispatch} = store
112+ const dispatchProps = this . doDispatchPropsDependOnOwnProps ?
113+ this . finalMapDispatchToProps ( dispatch , props ) :
114+ this . finalMapDispatchToProps ( dispatch )
115+
116+ return checkStateShape ( dispatchProps , true )
117+ }
118+
119+ configureFinalMapDispatch ( store , props ) {
120+ const mappedDispatch = mapDispatch ( store . dispatch , props )
121+ const isFactory = typeof mappedDispatch === 'function'
122+
123+ this . finalMapDispatchToProps = isFactory ?mappedDispatch :mapDispatch
124+ this . doDispatchPropsDependOnOwnProps = this . finalMapDispatchToProps . length !== 1
125+
126+ return isFactory ?
127+ this . computeDispatchProps ( store , props ) :
128+ checkStateShape ( mappedDispatch , true )
129+ }
130+
99131updateStatePropsIfNeeded ( ) {
100- const nextStateProps = computeStateProps ( this . store , this . props )
132+ const nextStateProps = this . computeStateProps ( this . store , this . props )
101133if ( this . stateProps && shallowEqual ( nextStateProps , this . stateProps ) ) {
102134return false
103135}
@@ -107,7 +139,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
107139}
108140
109141updateDispatchPropsIfNeeded ( ) {
110- const nextDispatchProps = computeDispatchProps ( this . store , this . props )
142+ const nextDispatchProps = this . computeDispatchProps ( this . store , this . props )
111143if ( this . dispatchProps && shallowEqual ( nextDispatchProps , this . dispatchProps ) ) {
112144return false
113145}
@@ -116,12 +148,14 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
116148return true
117149}
118150
119- updateMergedProps ( ) {
120- this . mergedProps = computeMergedProps (
121- this . stateProps ,
122- this . dispatchProps ,
123- this . props
124- )
151+ updateMergedPropsIfNeeded ( ) {
152+ const nextMergedProps = computeMergedProps ( this . stateProps , this . dispatchProps , this . props )
153+ if ( this . mergedProps && checkMergedEquals && shallowEqual ( nextMergedProps , this . mergedProps ) ) {
154+ return false
155+ }
156+
157+ this . mergedProps = nextMergedProps
158+ return true
125159}
126160
127161isSubscribed ( ) {
@@ -164,6 +198,8 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
164198this . haveOwnPropsChanged = true
165199this . hasStoreStateChanged = true
166200this . renderedElement = null
201+ this . finalMapDispatchToProps = null
202+ this . finalMapStateToProps = null
167203}
168204
169205handleChange ( ) {
@@ -203,10 +239,10 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
203239let shouldUpdateDispatchProps = true
204240if ( pure && renderedElement ) {
205241shouldUpdateStateProps = hasStoreStateChanged || (
206- haveOwnPropsChanged && doStatePropsDependOnOwnProps
242+ haveOwnPropsChanged && this . doStatePropsDependOnOwnProps
207243)
208244shouldUpdateDispatchProps =
209- haveOwnPropsChanged && doDispatchPropsDependOnOwnProps
245+ haveOwnPropsChanged && this . doDispatchPropsDependOnOwnProps
210246}
211247
212248let haveStatePropsChanged = false
@@ -224,7 +260,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
224260haveDispatchPropsChanged ||
225261haveOwnPropsChanged
226262) {
227- this . updateMergedProps ( )
263+ haveMergedPropsChanged = this . updateMergedPropsIfNeeded ( )
228264} else {
229265haveMergedPropsChanged = false
230266}