Skip to content

Commit 582b17f

Browse files
jimbollatimdorr
authored andcommitted
Shows more helpful error when connect() is passed invalid args. (#554)
1 parent d5180b5 commit 582b17f

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

src/components/connectAdvanced.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export default function connectAdvanced(
8585
storeKey,
8686
withRef,
8787
displayName,
88+
wrappedComponentName,
8889
WrappedComponent
8990
}
9091

src/connect/connect.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ import defaultSelectorFactory from './selectorFactory'
2222
it receives new props or store state.
2323
*/
2424

25-
function match(arg, factories) {
25+
function match(arg, factories, name) {
2626
for (let i = factories.length - 1; i >= 0; i--) {
2727
const result = factories[i](arg)
2828
if (result) return result
2929
}
30-
return undefined
30+
31+
return (dispatch, options) => {
32+
throw new Error(`Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.`)
33+
}
3134
}
3235

3336
function strictEqual(a, b) { return a === b }
@@ -54,9 +57,9 @@ export function createConnect({
5457
...extraOptions
5558
} = {}
5659
) {
57-
const initMapStateToProps = match(mapStateToProps, mapStateToPropsFactories)
58-
const initMapDispatchToProps = match(mapDispatchToProps, mapDispatchToPropsFactories)
59-
const initMergeProps = match(mergeProps, mergePropsFactories)
60+
const initMapStateToProps = match(mapStateToProps, mapStateToPropsFactories, 'mapStateToProps')
61+
const initMapDispatchToProps = match(mapDispatchToProps, mapDispatchToPropsFactories, 'mapDispatchToProps')
62+
const initMergeProps = match(mergeProps, mergePropsFactories, 'mergeProps')
6063

6164
return connectHOC(selectorFactory, {
6265
// used in error messages

test/components/connect.spec.js

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ describe('React', () => {
2424
return Children.only(this.props.children)
2525
}
2626
}
27+
ProviderMock.childContextTypes = {
28+
store: PropTypes.object.isRequired
29+
}
2730

2831
class ContextBoundStore {
2932
constructor(reducer) {
@@ -49,10 +52,6 @@ describe('React', () => {
4952
}
5053
}
5154

52-
ProviderMock.childContextTypes = {
53-
store: PropTypes.object.isRequired
54-
}
55-
5655
function stringBuilder(prev = '', action) {
5756
return action.type === 'APPEND'
5857
? prev + action.body
@@ -2083,6 +2082,48 @@ describe('React', () => {
20832082
store.dispatch({ type: 'ACTION' })
20842083
expect(renderCount).toBe(rendersBeforeStateChange + 1)
20852084
})
2086-
})
20872085

2086+
function renderWithBadConnect(Component) {
2087+
const store = createStore(() => ({}))
2088+
2089+
try {
2090+
TestUtils.renderIntoDocument(
2091+
<ProviderMock store={store}>
2092+
<Component pass="through" />
2093+
</ProviderMock>
2094+
)
2095+
return null
2096+
} catch (error) {
2097+
return error.message
2098+
}
2099+
}
2100+
it('should throw a helpful error for invalid mapStateToProps arguments', () => {
2101+
@connect('invalid')
2102+
class InvalidMapState extends React.Component { render() { return <div></div> } }
2103+
2104+
const error = renderWithBadConnect(InvalidMapState)
2105+
expect(error).toInclude('string')
2106+
expect(error).toInclude('mapStateToProps')
2107+
expect(error).toInclude('InvalidMapState')
2108+
})
2109+
it('should throw a helpful error for invalid mapDispatchToProps arguments', () => {
2110+
@connect(null, 'invalid')
2111+
class InvalidMapDispatch extends React.Component { render() { return <div></div> } }
2112+
2113+
const error = renderWithBadConnect(InvalidMapDispatch)
2114+
expect(error).toInclude('string')
2115+
expect(error).toInclude('mapDispatchToProps')
2116+
expect(error).toInclude('InvalidMapDispatch')
2117+
})
2118+
it('should throw a helpful error for invalid mergeProps arguments', () => {
2119+
@connect(null, null, 'invalid')
2120+
class InvalidMerge extends React.Component { render() { return <div></div> } }
2121+
2122+
const error = renderWithBadConnect(InvalidMerge)
2123+
expect(error).toInclude('string')
2124+
expect(error).toInclude('mergeProps')
2125+
expect(error).toInclude('InvalidMerge')
2126+
})
2127+
2128+
})
20882129
})

0 commit comments

Comments
 (0)