Skip to content

Commit 55995db

Browse files
committed
Another pass at overloading map*ToProps
1 parent 7a74c86 commit 55995db

File tree

1 file changed

+35
-27
lines changed

1 file changed

+35
-27
lines changed

src/components/connect.js

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,21 @@ const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
1717
function isFunction(fn) {
1818
return typeof fn === 'function'
1919
}
20-
function isFactory(fn) {
21-
return isFunction(fn) && fn.length === 0 && isFunction(fn())
22-
}
2320

2421
function getDisplayName(WrappedComponent) {
2522
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
2623
}
2724

25+
function checkStateShape(stateProps, dispatch) {
26+
invariant(
27+
isPlainObject(stateProps),
28+
'`%sToProps` must return an object. Instead received %s.',
29+
dispatch ? 'mapDispatch' : 'mapState',
30+
stateProps
31+
)
32+
return stateProps
33+
}
34+
2835
// Helps track hot reloading.
2936
let nextVersion = 0
3037

@@ -35,9 +42,6 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
3542
wrapActionCreators(mapDispatchToProps) :
3643
mapDispatchToProps || defaultMapDispatchToProps
3744

38-
const mapStateFactory = isFactory(mapState) ? mapState : (() => mapState)
39-
const mapDispatchFactory = isFactory(mapDispatch) ? mapDispatch : (() => mapDispatch)
40-
4145
const finalMergeProps = mergeProps || defaultMergeProps
4246
const { pure = true, withRef = false } = options
4347

@@ -62,45 +66,48 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
6266
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
6367
)
6468

65-
this.configure()
6669
const storeState = this.store.getState()
6770
this.state = { storeState }
6871
this.clearCache()
6972
}
7073

71-
configure() {
72-
this.finalMapStateToProps = mapStateFactory()
73-
this.finalMapDispatchToProps = mapDispatchFactory()
74-
this.doStatePropsDependOnOwnProps = this.finalMapStateToProps.length !== 1
75-
this.doDispatchPropsDependOnOwnProps = this.finalMapDispatchToProps.length !== 1
76-
}
77-
7874
computeStateProps(store, props) {
75+
if (!this.finalMapStateToProps) {
76+
return this.configureFinalMapState(store, props)
77+
}
7978
const state = store.getState()
8079
const stateProps = this.doStatePropsDependOnOwnProps ?
8180
this.finalMapStateToProps(state, props) :
8281
this.finalMapStateToProps(state)
8382

84-
invariant(
85-
isPlainObject(stateProps),
86-
'`mapStateToProps` must return an object. Instead received %s.',
87-
stateProps
88-
)
89-
return stateProps
83+
return checkStateShape(stateProps)
84+
}
85+
86+
configureFinalMapState(store, props) {
87+
const mappedState = mapState(store.getState(), props)
88+
const isFactory = isFunction(mappedState)
89+
this.finalMapStateToProps = isFactory ? mappedState : mapState
90+
this.doStatePropsDependOnOwnProps = this.finalMapStateToProps.length !== 1
91+
return isFactory ? this.computeStateProps(store, props) : checkStateShape(mappedState)
9092
}
9193

9294
computeDispatchProps(store, props) {
95+
if (!this.finalMapDispatchToProps) {
96+
return this.configureFinalMapDispatch(store, props)
97+
}
9398
const { dispatch } = store
9499
const dispatchProps = this.doDispatchPropsDependOnOwnProps ?
95100
this.finalMapDispatchToProps(dispatch, props) :
96101
this.finalMapDispatchToProps(dispatch)
102+
return checkStateShape(dispatchProps, true)
103+
}
97104

98-
invariant(
99-
isPlainObject(dispatchProps),
100-
'`mapDispatchToProps` must return an object. Instead received %s.',
101-
dispatchProps
102-
)
103-
return dispatchProps
105+
configureFinalMapDispatch(store, props) {
106+
const mappedDispatch = mapDispatch(store.dispatch, props)
107+
const isFactory = isFunction(mappedDispatch)
108+
this.finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch
109+
this.doDispatchPropsDependOnOwnProps = this.finalMapDispatchToProps.length !== 1
110+
return isFactory ? this.computeDispatchProps(store, props) : checkStateShape(mappedDispatch, true)
104111
}
105112

106113
computeMergedProps(stateProps, dispatchProps, parentProps) {
@@ -181,6 +188,8 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
181188
this.haveOwnPropsChanged = true
182189
this.hasStoreStateChanged = true
183190
this.renderedElement = null
191+
this.finalMapDispatchToProps = null
192+
this.finalMapStateToProps = null
184193
}
185194

186195
handleChange() {
@@ -282,7 +291,6 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
282291

283292
// We are hot reloading!
284293
this.version = version
285-
this.configure()
286294
this.trySubscribe()
287295
this.clearCache()
288296
}

0 commit comments

Comments
 (0)