Skip to content

Commit f15b244

Browse files
committed
Fix support for falsy arguments
1 parent 46508ae commit f15b244

File tree

2 files changed

+36
-31
lines changed

2 files changed

+36
-31
lines changed

src/components/createConnect.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ export default function createConnect(React) {
3737
const { Component, PropTypes } = React;
3838
const storeShape = createStoreShape(PropTypes);
3939

40-
return function connect(
41-
mapStateToProps = defaultMapStateToProps,
42-
actionCreatorsOrMapDispatchToProps = defaultMapDispatchToProps,
43-
mergeProps = defaultMergeProps
44-
) {
45-
const shouldSubscribe = mapStateToProps !== defaultMapStateToProps;
46-
const mapDispatchToProps = isPlainObject(actionCreatorsOrMapDispatchToProps) ?
47-
wrapActionCreators(actionCreatorsOrMapDispatchToProps) :
48-
actionCreatorsOrMapDispatchToProps;
40+
return function connect(mapStateToProps, mapDispatchToProps, mergeProps) {
41+
const shouldSubscribe = Boolean(mapStateToProps);
42+
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps;
43+
const finalMapDispatchToProps = isPlainObject(mapDispatchToProps) ?
44+
wrapActionCreators(mapDispatchToProps) :
45+
mapDispatchToProps || defaultMapDispatchToProps;
46+
const finalMergeProps = mergeProps || defaultMergeProps;
4947

5048
// Helps track hot reloading.
5149
const version = nextVersion++;
@@ -127,7 +125,7 @@ export default function createConnect(React) {
127125

128126
mapState(props = this.props, context = this.context) {
129127
const state = context.store.getState();
130-
const stateProps = mapStateToProps(state);
128+
const stateProps = finalMapStateToProps(state);
131129

132130
invariant(
133131
isPlainObject(stateProps),
@@ -140,7 +138,7 @@ export default function createConnect(React) {
140138

141139
mapDispatch(context = this.context) {
142140
const { dispatch } = context.store;
143-
const dispatchProps = mapDispatchToProps(dispatch);
141+
const dispatchProps = finalMapDispatchToProps(dispatch);
144142

145143
invariant(
146144
isPlainObject(dispatchProps),
@@ -153,7 +151,7 @@ export default function createConnect(React) {
153151

154152
merge(props = this.props, state = this.state) {
155153
const { stateProps, dispatchProps } = state;
156-
const merged = mergeProps(stateProps, dispatchProps, props);
154+
const merged = finalMergeProps(stateProps, dispatchProps, props);
157155

158156
invariant(
159157
isPlainObject(merged),

test/components/connect.spec.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -244,31 +244,38 @@ describe('React', () => {
244244
expect(decorated.isSubscribed()).toBe(true);
245245
});
246246

247-
it('should not subscribe to stores if mapState argument is falsy', () => {
247+
it('should pass dispatch and avoid subscription if arguments are falsy', () => {
248248
const store = createStore(() => ({
249249
foo: 'bar'
250250
}));
251251

252-
@connect()
253-
class Container extends Component {
254-
render() {
255-
return <div {...this.props} />;
252+
function runCheck(...connectArgs) {
253+
@connect(...connectArgs)
254+
class Container extends Component {
255+
render() {
256+
return <div {...this.props} />;
257+
}
256258
}
259+
260+
const container = TestUtils.renderIntoDocument(
261+
<Provider store={store}>
262+
{() => <Container pass='through' />}
263+
</Provider>
264+
);
265+
const div = TestUtils.findRenderedDOMComponentWithTag(container, 'div');
266+
expect(div.props.dispatch).toEqual(store.dispatch);
267+
expect(div.props.foo).toBe(undefined);
268+
expect(div.props.pass).toEqual('through');
269+
expect(() =>
270+
TestUtils.findRenderedComponentWithType(container, Container)
271+
).toNotThrow();
272+
const decorated = TestUtils.findRenderedComponentWithType(container, Container);
273+
expect(decorated.isSubscribed()).toBe(false);
257274
}
258275

259-
const container = TestUtils.renderIntoDocument(
260-
<Provider store={store}>
261-
{() => <Container pass='through' />}
262-
</Provider>
263-
);
264-
const div = TestUtils.findRenderedDOMComponentWithTag(container, 'div');
265-
expect(div.props.dispatch).toEqual(store.dispatch);
266-
expect(div.props.foo).toBe(undefined);
267-
expect(() =>
268-
TestUtils.findRenderedComponentWithType(container, Container)
269-
).toNotThrow();
270-
const decorated = TestUtils.findRenderedComponentWithType(container, Container);
271-
expect(decorated.isSubscribed()).toNotBe(true);
276+
runCheck();
277+
runCheck(null, null, null);
278+
runCheck(false, false, false);
272279
});
273280

274281
it('should unsubscribe before unmounting', () => {
@@ -439,7 +446,7 @@ describe('React', () => {
439446
const store = createStore(() => {});
440447

441448
@connect(
442-
undefined,
449+
null,
443450
() => ({ scooby: 'doo' })
444451
)
445452
class ContainerBefore extends Component {

0 commit comments

Comments
 (0)