Skip to content

Commit 7a74c86

Browse files
committed
Attempt at overloading arguments with factories
1 parent 22cf67b commit 7a74c86

File tree

1 file changed

+66
-48
lines changed

1 file changed

+66
-48
lines changed

src/components/connect.js

Lines changed: 66 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
1414
...dispatchProps
1515
})
1616

17+
function isFunction(fn) {
18+
return typeof fn === 'function'
19+
}
20+
function isFactory(fn) {
21+
return isFunction(fn) && fn.length === 0 && isFunction(fn())
22+
}
23+
1724
function getDisplayName(WrappedComponent) {
1825
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
1926
}
@@ -23,56 +30,20 @@ let nextVersion = 0
2330

2431
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
2532
const shouldSubscribe = Boolean(mapStateToProps)
26-
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps
27-
const finalMapDispatchToProps = isPlainObject(mapDispatchToProps) ?
33+
const mapState = mapStateToProps || defaultMapStateToProps
34+
const mapDispatch = isPlainObject(mapDispatchToProps) ?
2835
wrapActionCreators(mapDispatchToProps) :
2936
mapDispatchToProps || defaultMapDispatchToProps
37+
38+
const mapStateFactory = isFactory(mapState) ? mapState : (() => mapState)
39+
const mapDispatchFactory = isFactory(mapDispatch) ? mapDispatch : (() => mapDispatch)
40+
3041
const finalMergeProps = mergeProps || defaultMergeProps
31-
const doStatePropsDependOnOwnProps = finalMapStateToProps.length !== 1
32-
const doDispatchPropsDependOnOwnProps = finalMapDispatchToProps.length !== 1
3342
const { pure = true, withRef = false } = options
3443

3544
// Helps track hot reloading.
3645
const version = nextVersion++
3746

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-
7647
return function wrapWithConnect(WrappedComponent) {
7748
class Connect extends Component {
7849
shouldComponentUpdate() {
@@ -91,13 +62,59 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
9162
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
9263
)
9364

65+
this.configure()
9466
const storeState = this.store.getState()
9567
this.state = { storeState }
9668
this.clearCache()
9769
}
9870

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+
78+
computeStateProps(store, props) {
79+
const state = store.getState()
80+
const stateProps = this.doStatePropsDependOnOwnProps ?
81+
this.finalMapStateToProps(state, props) :
82+
this.finalMapStateToProps(state)
83+
84+
invariant(
85+
isPlainObject(stateProps),
86+
'`mapStateToProps` must return an object. Instead received %s.',
87+
stateProps
88+
)
89+
return stateProps
90+
}
91+
92+
computeDispatchProps(store, props) {
93+
const { dispatch } = store
94+
const dispatchProps = this.doDispatchPropsDependOnOwnProps ?
95+
this.finalMapDispatchToProps(dispatch, props) :
96+
this.finalMapDispatchToProps(dispatch)
97+
98+
invariant(
99+
isPlainObject(dispatchProps),
100+
'`mapDispatchToProps` must return an object. Instead received %s.',
101+
dispatchProps
102+
)
103+
return dispatchProps
104+
}
105+
106+
computeMergedProps(stateProps, dispatchProps, parentProps) {
107+
const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps)
108+
invariant(
109+
isPlainObject(mergedProps),
110+
'`mergeProps` must return an object. Instead received %s.',
111+
mergedProps
112+
)
113+
return mergedProps
114+
}
115+
99116
updateStatePropsIfNeeded() {
100-
const nextStateProps = computeStateProps(this.store, this.props)
117+
const nextStateProps = this.computeStateProps(this.store, this.props)
101118
if (this.stateProps && shallowEqual(nextStateProps, this.stateProps)) {
102119
return false
103120
}
@@ -107,7 +124,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
107124
}
108125

109126
updateDispatchPropsIfNeeded() {
110-
const nextDispatchProps = computeDispatchProps(this.store, this.props)
127+
const nextDispatchProps = this.computeDispatchProps(this.store, this.props)
111128
if (this.dispatchProps && shallowEqual(nextDispatchProps, this.dispatchProps)) {
112129
return false
113130
}
@@ -117,15 +134,15 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
117134
}
118135

119136
updateMergedProps() {
120-
this.mergedProps = computeMergedProps(
137+
this.mergedProps = this.computeMergedProps(
121138
this.stateProps,
122139
this.dispatchProps,
123140
this.props
124141
)
125142
}
126143

127144
isSubscribed() {
128-
return typeof this.unsubscribe === 'function'
145+
return isFunction(this.unsubscribe)
129146
}
130147

131148
trySubscribe() {
@@ -203,10 +220,10 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
203220
let shouldUpdateDispatchProps = true
204221
if (pure && renderedElement) {
205222
shouldUpdateStateProps = hasStoreStateChanged || (
206-
haveOwnPropsChanged && doStatePropsDependOnOwnProps
223+
haveOwnPropsChanged && this.doStatePropsDependOnOwnProps
207224
)
208225
shouldUpdateDispatchProps =
209-
haveOwnPropsChanged && doDispatchPropsDependOnOwnProps
226+
haveOwnPropsChanged && this.doDispatchPropsDependOnOwnProps
210227
}
211228

212229
let haveStatePropsChanged = false
@@ -265,6 +282,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
265282

266283
// We are hot reloading!
267284
this.version = version
285+
this.configure()
268286
this.trySubscribe()
269287
this.clearCache()
270288
}

0 commit comments

Comments
 (0)