diff --git a/src/components/createConnectDecorator.js b/src/components/createConnectDecorator.js
index cdd501d67e..4977f6799e 100644
--- a/src/components/createConnectDecorator.js
+++ b/src/components/createConnectDecorator.js
@@ -4,7 +4,7 @@ import shallowEqualScalar from '../utils/shallowEqualScalar';
export default function createConnectDecorator(React, Connector) {
const { Component } = React;
- return function connect(select) {
+ return function connect(select, actionCreators) {
return DecoratedComponent => class ConnectorDecorator extends Component {
static displayName = `Connector(${getDisplayName(DecoratedComponent)})`;
@@ -14,7 +14,10 @@ export default function createConnectDecorator(React, Connector) {
render() {
return (
-
select(state, this.props)}>
+ select(state, this.props)}
+ actionCreators={actionCreators}
+ >
{stuff => }
);
diff --git a/src/components/createConnector.js b/src/components/createConnector.js
index 0d21f49c50..465d2296c8 100644
--- a/src/components/createConnector.js
+++ b/src/components/createConnector.js
@@ -1,8 +1,11 @@
import identity from 'lodash/utility/identity';
import shallowEqual from '../utils/shallowEqual';
+import bindActionCreators from '../utils/bindActionCreators';
+
import isPlainObject from 'lodash/lang/isPlainObject';
import invariant from 'invariant';
+
export default function createConnector(React) {
const { Component, PropTypes } = React;
@@ -13,11 +16,13 @@ export default function createConnector(React) {
static propTypes = {
children: PropTypes.func.isRequired,
- select: PropTypes.func.isRequired
+ select: PropTypes.func.isRequired,
+ actionCreators: PropTypes.object
};
static defaultProps = {
- select: identity
+ select: identity,
+ actionCreators: {}
};
shouldComponentUpdate(nextProps, nextState) {
@@ -41,6 +46,7 @@ export default function createConnector(React) {
this.unsubscribe = context.redux.subscribe(::this.handleChange);
this.state = this.selectState({ context, props });
+ this.boundActions = this.bindActionCreators(props.actionCreators, context.redux.dispatch);
}
componentWillReceiveProps(nextProps) {
@@ -48,6 +54,10 @@ export default function createConnector(React) {
// Force the state slice recalculation
this.handleChange();
}
+
+ if (nextProps.actionCreators !== this.props.actionCreators) {
+ this.boundActions = this.bindActionCreators(nextProps.actionCreators, this.context.redux.dispatch);
+ }
}
componentWillUnmount() {
@@ -71,12 +81,18 @@ export default function createConnector(React) {
return { slice };
}
+ bindActionCreators = (actionCreators, dispatch) => {
+ return {
+ actions: bindActionCreators(actionCreators, dispatch)
+ };
+ }
+
render() {
const { children } = this.props;
const { slice } = this.state;
const { redux: { dispatch } } = this.context;
- return children({ dispatch, ...slice });
+ return children({ dispatch, ...slice, ...this.boundActions });
}
};
}
diff --git a/test/components/Connector.spec.js b/test/components/Connector.spec.js
index 9b135d7296..4362bd9bfa 100644
--- a/test/components/Connector.spec.js
+++ b/test/components/Connector.spec.js
@@ -145,6 +145,30 @@ describe('React', () => {
expect(div.props.dispatch).toBe(redux.dispatch);
});
+ it('properly binds and passes action creators when passed as an object', () => {
+ const redux = createRedux({ test: () => 'test'});
+
+ const testActions = {
+ anAction: () => {
+ return { type: 'TEST_ACTION' };
+ }
+ };
+
+ const tree = TestUtils.renderIntoDocument(
+
+ {() => (
+
+ {({ dispatch, actions }) => }
+
+ )}
+
+ );
+
+ const div = TestUtils.findRenderedDOMComponentWithTag(tree, 'div');
+ expect(Object.keys(div.props.actions)).toEqual(Object.keys(testActions));
+ expect(div.props.actions.anAction).toBeA('function');
+ });
+
it('should throw an error if `state` returns anything but a plain object', () => {
const redux = createRedux(() => {});