Skip to content

Commit 74d37d9

Browse files
committed
feat(createPubSubConnector): Added boolean option { forceInitialValues }, default to false
When set to true if 'mapSubscriptionsToProps' is an object all mapped actions will be invoked once when component will mount.
1 parent 4289f21 commit 74d37d9

File tree

2 files changed

+95
-4
lines changed

2 files changed

+95
-4
lines changed

src/components/createPubSubConnector.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
4444
mapPublishToProps || defaultMapPublishToProps;
4545
const shouldUpdatePublishProps = finalMapPublishToProps.length > 1;
4646

47-
const { withRef = false, ownProps = true } = options || {};
47+
const { withRef = false, ownProps = true, forceInitialValues = false } = options || {};
4848

4949
let mappedSubscriptions = {};
5050
function registerMappedSubscriptions(pubSub, subscriptionsMap = {}, updateSubscriptionProps, getProps) {
@@ -105,11 +105,24 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
105105
mappedSubscriptions = Object.keys(subscriptionsMap)
106106
.reduce((acc, key) => {
107107
const callback = updateMappedSubscriptions(key, subscriptionsMap[key]);
108-
acc[key] = add(key, callback);
108+
acc[key] = {
109+
callback,
110+
originalCallback: subscriptionsMap[key],
111+
unsubscribe: add(key, callback),
112+
};
109113
return acc;
110114
}, {});
111115
}
112116

117+
function invokeMappedSubscriptions() {
118+
mappedSubscriptions = Object.keys(mappedSubscriptions)
119+
.forEach(key => {
120+
const { callback, originalCallback } = mappedSubscriptions[key];
121+
const initialValues = Array.isArray(originalCallback.initialValues) ? originalCallback.initialValues : [];
122+
callback(...initialValues);
123+
});
124+
}
125+
113126
function initSubscriptionFunction(pubSub, subscriptionsFunction, updateSubscriptionProps, getProps) {
114127
// init given function, this invocation will subscribe required actions to
115128
// passed pubSub instance
@@ -154,7 +167,7 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
154167
+ `or explicitly pass "pubSubCore" as a prop to "${this.constructor.displayName}".`
155168
);
156169
}
157-
170+
this.state = {};
158171
this.pubSub = this.pubSubCore.register(this);
159172
this.mappedSubscriptionProps = {};
160173

@@ -186,8 +199,12 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
186199
}
187200

188201
this.publishProps = computePublishProps(this.pubSub, props);
202+
}
189203

190-
this.state = {};
204+
componentWillMount() {
205+
if (forceInitialValues) {
206+
invokeMappedSubscriptions();
207+
}
191208
}
192209

193210
shouldComponentUpdate(nextProps, nextState) {

test/components/createPubSubConnector.spec.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,3 +1082,77 @@ test(
10821082
t.end();
10831083
}
10841084
);
1085+
1086+
test(
1087+
'should invoke all actions mapped when component is instantiated'
1088+
+ ' and option is { forceInitialValues: true }',
1089+
t => {
1090+
const SIMPLE_UPDATE = 'simpleUpdate';
1091+
const pubSubCore = createPubSub();
1092+
1093+
class Container extends Component {
1094+
render() {
1095+
return (<Passthrough {...this.props} />);
1096+
}
1097+
}
1098+
1099+
const simpleUpdateHandler = (country = 'unknown country') => {
1100+
console.log('PD', country);
1101+
return { country };
1102+
};
1103+
simpleUpdateHandler.initialValues = ['default country'];
1104+
1105+
const WrapperContainer = createPubSubConnector(
1106+
{ [SIMPLE_UPDATE]: simpleUpdateHandler },
1107+
null, { forceInitialValues: true }
1108+
)(Container);
1109+
1110+
const tree = TestUtils.renderIntoDocument(
1111+
<ProviderMock pubSubCore={pubSubCore}>
1112+
<WrapperContainer />
1113+
</ProviderMock>
1114+
);
1115+
const stub = TestUtils.findRenderedComponentWithType(tree, Passthrough);
1116+
1117+
t.is(stub.props.country, 'default country');
1118+
1119+
t.end();
1120+
}
1121+
);
1122+
1123+
test(
1124+
'should not invoke actions mapped when component is instantiated'
1125+
+ ' but option is { forceInitialValues: false }',
1126+
t => {
1127+
const SIMPLE_UPDATE = 'simpleUpdate';
1128+
const pubSubCore = createPubSub();
1129+
1130+
class Container extends Component {
1131+
render() {
1132+
return (<Passthrough {...this.props} />);
1133+
}
1134+
}
1135+
1136+
const simpleUpdateHandler = (country = 'unknown country') => {
1137+
console.log('PD', country);
1138+
return { country };
1139+
};
1140+
simpleUpdateHandler.initialValues = ['default country'];
1141+
1142+
const WrapperContainer = createPubSubConnector(
1143+
{ [SIMPLE_UPDATE]: simpleUpdateHandler },
1144+
null, { forceInitialValues: false }
1145+
)(Container);
1146+
1147+
const tree = TestUtils.renderIntoDocument(
1148+
<ProviderMock pubSubCore={pubSubCore}>
1149+
<WrapperContainer />
1150+
</ProviderMock>
1151+
);
1152+
const stub = TestUtils.findRenderedComponentWithType(tree, Passthrough);
1153+
1154+
t.is(stub.props.country, undefined);
1155+
1156+
t.end();
1157+
}
1158+
);

0 commit comments

Comments
 (0)