Skip to content

Commit 71de169

Browse files
committed
Merge pull request #335 from chentsulin/improve-mapStateToProps-invariant
Close #309, Improve invariant validation error message
2 parents e55e93a + a2f620b commit 71de169

File tree

2 files changed

+34
-36
lines changed

2 files changed

+34
-36
lines changed

src/components/connect.js

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,6 @@ 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-
3121
// Helps track hot reloading.
3222
let nextVersion = 0
3323

@@ -45,17 +35,25 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
4535
// Helps track hot reloading.
4636
const version = nextVersion++
4737

48-
function computeMergedProps(stateProps, dispatchProps, parentProps) {
49-
const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps)
50-
invariant(
51-
isPlainObject(mergedProps),
52-
'`mergeProps` must return an object. Instead received %s.',
53-
mergedProps
54-
)
55-
return mergedProps
56-
}
57-
5838
return function wrapWithConnect(WrappedComponent) {
39+
const connectDisplayName = `Connect(${getDisplayName(WrappedComponent)})`
40+
41+
function checkStateShape(props, methodName) {
42+
invariant(
43+
isPlainObject(props),
44+
'`%s %s` must return an object. Instead received %s.',
45+
connectDisplayName,
46+
methodName,
47+
props
48+
)
49+
return props
50+
}
51+
52+
function computeMergedProps(stateProps, dispatchProps, parentProps) {
53+
const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps)
54+
return checkStateShape(mergedProps, 'mergeProps')
55+
}
56+
5957
class Connect extends Component {
6058
shouldComponentUpdate() {
6159
return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged
@@ -68,9 +66,9 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
6866

6967
invariant(this.store,
7068
`Could not find "store" in either the context or ` +
71-
`props of "${this.constructor.displayName}". ` +
69+
`props of "${connectDisplayName}". ` +
7270
`Either wrap the root component in a <Provider>, ` +
73-
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
71+
`or explicitly pass "store" as a prop to "${connectDisplayName}".`
7472
)
7573

7674
const storeState = this.store.getState()
@@ -88,7 +86,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
8886
this.finalMapStateToProps(state, props) :
8987
this.finalMapStateToProps(state)
9088

91-
return checkStateShape(stateProps)
89+
return checkStateShape(stateProps, 'mapStateToProps')
9290
}
9391

9492
configureFinalMapState(store, props) {
@@ -100,7 +98,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
10098

10199
return isFactory ?
102100
this.computeStateProps(store, props) :
103-
checkStateShape(mappedState)
101+
checkStateShape(mappedState, 'mapStateToProps')
104102
}
105103

106104
computeDispatchProps(store, props) {
@@ -113,7 +111,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
113111
this.finalMapDispatchToProps(dispatch, props) :
114112
this.finalMapDispatchToProps(dispatch)
115113

116-
return checkStateShape(dispatchProps, true)
114+
return checkStateShape(dispatchProps, 'mapDispatchToProps')
117115
}
118116

119117
configureFinalMapDispatch(store, props) {
@@ -125,7 +123,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
125123

126124
return isFactory ?
127125
this.computeDispatchProps(store, props) :
128-
checkStateShape(mappedDispatch, true)
126+
checkStateShape(mappedDispatch, 'mapDispatchToProps')
129127
}
130128

131129
updateStatePropsIfNeeded() {
@@ -284,7 +282,7 @@ export default function connect(mapStateToProps, mapDispatchToProps, mergeProps,
284282
}
285283
}
286284

287-
Connect.displayName = `Connect(${getDisplayName(WrappedComponent)})`
285+
Connect.displayName = connectDisplayName
288286
Connect.WrappedComponent = WrappedComponent
289287
Connect.contextTypes = {
290288
store: storeShape

test/components/connect.spec.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,71 +1004,71 @@ describe('React', () => {
10041004
{makeContainer(() => 1, () => ({}), () => ({}))}
10051005
</ProviderMock>
10061006
)
1007-
}).toThrow(/mapState/)
1007+
}).toThrow(/Connect\(Container\) mapState/)
10081008

10091009
expect(() => {
10101010
TestUtils.renderIntoDocument(
10111011
<ProviderMock store={store}>
10121012
{makeContainer(() => 'hey', () => ({}), () => ({}))}
10131013
</ProviderMock>
10141014
)
1015-
}).toThrow(/mapState/)
1015+
}).toThrow(/Connect\(Container\) mapState/)
10161016

10171017
expect(() => {
10181018
TestUtils.renderIntoDocument(
10191019
<ProviderMock store={store}>
10201020
{makeContainer(() => new AwesomeMap(), () => ({}), () => ({}))}
10211021
</ProviderMock>
10221022
)
1023-
}).toThrow(/mapState/)
1023+
}).toThrow(/Connect\(Container\) mapState/)
10241024

10251025
expect(() => {
10261026
TestUtils.renderIntoDocument(
10271027
<ProviderMock store={store}>
10281028
{makeContainer(() => ({}), () => 1, () => ({}))}
10291029
</ProviderMock>
10301030
)
1031-
}).toThrow(/mapDispatch/)
1031+
}).toThrow(/Connect\(Container\) mapDispatch/)
10321032

10331033
expect(() => {
10341034
TestUtils.renderIntoDocument(
10351035
<ProviderMock store={store}>
10361036
{makeContainer(() => ({}), () => 'hey', () => ({}))}
10371037
</ProviderMock>
10381038
)
1039-
}).toThrow(/mapDispatch/)
1039+
}).toThrow(/Connect\(Container\) mapDispatch/)
10401040

10411041
expect(() => {
10421042
TestUtils.renderIntoDocument(
10431043
<ProviderMock store={store}>
10441044
{makeContainer(() => ({}), () => new AwesomeMap(), () => ({}))}
10451045
</ProviderMock>
10461046
)
1047-
}).toThrow(/mapDispatch/)
1047+
}).toThrow(/Connect\(Container\) mapDispatch/)
10481048

10491049
expect(() => {
10501050
TestUtils.renderIntoDocument(
10511051
<ProviderMock store={store}>
10521052
{makeContainer(() => ({}), () => ({}), () => 1)}
10531053
</ProviderMock>
10541054
)
1055-
}).toThrow(/mergeProps/)
1055+
}).toThrow(/Connect\(Container\) mergeProps/)
10561056

10571057
expect(() => {
10581058
TestUtils.renderIntoDocument(
10591059
<ProviderMock store={store}>
10601060
{makeContainer(() => ({}), () => ({}), () => 'hey')}
10611061
</ProviderMock>
10621062
)
1063-
}).toThrow(/mergeProps/)
1063+
}).toThrow(/Connect\(Container\) mergeProps/)
10641064

10651065
expect(() => {
10661066
TestUtils.renderIntoDocument(
10671067
<ProviderMock store={store}>
10681068
{makeContainer(() => ({}), () => ({}), () => new AwesomeMap())}
10691069
</ProviderMock>
10701070
)
1071-
}).toThrow(/mergeProps/)
1071+
}).toThrow(/Connect\(Container\) mergeProps/)
10721072
})
10731073

10741074
it('should recalculate the state and rebind the actions on hot update', () => {

0 commit comments

Comments
 (0)