Skip to content

Commit 25f97c7

Browse files
committed
connect() wraps connectFactory(), attaching prop configuration to component
1 parent 777652d commit 25f97c7

File tree

2 files changed

+68
-59
lines changed

2 files changed

+68
-59
lines changed

src/components/connect.js

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -21,58 +21,15 @@ function getDisplayName(WrappedComponent) {
2121
// Helps track hot reloading.
2222
let nextVersion = 0
2323

24-
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
25-
const shouldSubscribe = Boolean(mapStateToProps)
26-
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps
27-
const finalMapDispatchToProps = isPlainObject(mapDispatchToProps) ?
28-
wrapActionCreators(mapDispatchToProps) :
29-
mapDispatchToProps || defaultMapDispatchToProps
24+
export function connectFactory(mapStateToPropsFactory, mapDispatchToPropsFactory, mergeProps, options = {}) {
3025
const finalMergeProps = mergeProps || defaultMergeProps
31-
const shouldUpdateStateProps = finalMapStateToProps.length > 1
32-
const shouldUpdateDispatchProps = finalMapDispatchToProps.length > 1
26+
const finalMapStateToPropsFactory = mapStateToPropsFactory || () => defaultMapStateToProps
27+
const finalMapDispatchToPropsFactory = mapDispatchToPropsFactory || () => defaultMapDispatchToProps
3328
const { pure = true, withRef = false } = options
3429

3530
// Helps track hot reloading.
3631
const version = nextVersion++
3732

38-
function computeStateProps(store, props) {
39-
const state = store.getState()
40-
const stateProps = shouldUpdateStateProps ?
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 = shouldUpdateDispatchProps ?
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 computeNextState(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-
7633
return function wrapWithConnect(WrappedComponent) {
7734
class Connect extends Component {
7835
shouldComponentUpdate(nextProps, nextState) {
@@ -88,11 +45,11 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
8845
let mapStateProducedChange = false
8946
let dispatchPropsChanged = false
9047

91-
if (storeChanged || (propsChanged && shouldUpdateStateProps)) {
48+
if (storeChanged || (propsChanged && this.shouldUpdateStateProps)) {
9249
mapStateProducedChange = this.updateStateProps(nextProps)
9350
}
9451

95-
if (propsChanged && shouldUpdateDispatchProps) {
52+
if (propsChanged && this.shouldUpdateDispatchProps) {
9653
dispatchPropsChanged = this.updateDispatchProps(nextProps)
9754
}
9855

@@ -116,22 +73,61 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
11673
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
11774
)
11875

119-
this.stateProps = computeStateProps(this.store, props)
120-
this.dispatchProps = computeDispatchProps(this.store, props)
76+
this.configure()
77+
this.stateProps = this.computeStateProps()
78+
this.dispatchProps = this.computeDispatchProps()
12179
this.state = { storeState: null }
12280
this.updateState()
12381
}
12482

125-
computeNextState(props = this.props) {
126-
return computeNextState(
127-
this.stateProps,
128-
this.dispatchProps,
129-
props
83+
configure() {
84+
this.shouldSubscribe = Boolean(mapStateToPropsFactory)
85+
this.finalMapStateToProps = finalMapStateToPropsFactory()
86+
this.finalMapDispatchToProps = finalMapDispatchToPropsFactory()
87+
this.shouldUpdateStateProps = this.finalMapStateToProps.length > 1
88+
this.shouldUpdateDispatchProps = this.finalMapDispatchToProps.length > 1
89+
}
90+
91+
computeStateProps(props = this.props) {
92+
const state = this.store.getState()
93+
const stateProps = this.shouldUpdateStateProps ?
94+
this.finalMapStateToProps(state, props) :
95+
this.finalMapStateToProps(state)
96+
97+
invariant(
98+
isPlainObject(stateProps),
99+
'`mapStateToProps` must return an object. Instead received %s.',
100+
stateProps
101+
)
102+
return stateProps
103+
}
104+
105+
computeDispatchProps(props = this.props) {
106+
const { dispatch } = this.store
107+
const dispatchProps = this.shouldUpdateDispatchProps ?
108+
this.finalMapDispatchToProps(dispatch, props) :
109+
this.finalMapDispatchToProps(dispatch)
110+
111+
invariant(
112+
isPlainObject(dispatchProps),
113+
'`mapDispatchToProps` must return an object. Instead received %s.',
114+
dispatchProps
130115
)
116+
return dispatchProps
117+
}
118+
119+
computeNextState(parentProps = this.props) {
120+
const mergedProps = finalMergeProps(this.stateProps, this.dispatchProps, parentProps)
121+
invariant(
122+
isPlainObject(mergedProps),
123+
'`mergeProps` must return an object. Instead received %s.',
124+
mergedProps
125+
)
126+
return mergedProps
131127
}
132128

133129
updateStateProps(props = this.props) {
134-
const nextStateProps = computeStateProps(this.store, props)
130+
const nextStateProps = this.computeStateProps(props)
135131
if (shallowEqual(nextStateProps, this.stateProps)) {
136132
return false
137133
}
@@ -141,7 +137,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
141137
}
142138

143139
updateDispatchProps(props = this.props) {
144-
const nextDispatchProps = computeDispatchProps(this.store, props)
140+
const nextDispatchProps = this.computeDispatchProps(props)
145141
if (shallowEqual(nextDispatchProps, this.dispatchProps)) {
146142
return false
147143
}
@@ -159,7 +155,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
159155
}
160156

161157
trySubscribe() {
162-
if (shouldSubscribe && !this.unsubscribe) {
158+
if (this.shouldSubscribe && !this.unsubscribe) {
163159
this.unsubscribe = this.store.subscribe(::this.handleChange)
164160
this.handleChange()
165161
}
@@ -226,6 +222,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
226222
this.version = version
227223

228224
// Update the state and bindings.
225+
this.configure()
229226
this.trySubscribe()
230227
this.updateStateProps()
231228
this.updateDispatchProps()
@@ -236,3 +233,15 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
236233
return hoistStatics(Connect, WrappedComponent)
237234
}
238235
}
236+
237+
export function connect(mapStateToProps, mapDispatchToProps, mergeProps, options) {
238+
const configuredMapDispatch = isPlainObject(mapDispatchToProps) ?
239+
wrapActionCreators(mapDispatchToProps) :
240+
mapDispatchToProps
241+
return connectFactory(
242+
mapStateToProps ? () => mapStateToProps : null,
243+
configuredMapDispatch ? () => configuredMapDispatch : null,
244+
mergeProps,
245+
options
246+
)
247+
}

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { default as Provider } from './components/Provider'
2-
export { default as connect } from './components/connect'
2+
export { connect, connectFactory } from './components/connect'

0 commit comments

Comments
 (0)