Skip to content

Commit 4289f21

Browse files
committed
feat(createPubSubConnector): 'mapSubscriptionsToProps' now can be a function responsible of mapping
If given a function the signature must be fn(pubSub, updateSubscriptionProps, getProps) and must return a function with signature fn(props). The returned function must return an object
1 parent dddb2e8 commit 4289f21

File tree

2 files changed

+413
-11
lines changed

2 files changed

+413
-11
lines changed

src/components/createPubSubConnector.js

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,23 @@ function cleanEmptyKeys(obj = {}) {
2727
}
2828

2929
export default function createPubSubConnector(mapSubscriptionsToProps, mapPublishToProps, options = {}) {
30+
if (
31+
mapSubscriptionsToProps &&
32+
(typeof mapSubscriptionsToProps !== 'function' && !isPlainObject(mapSubscriptionsToProps))
33+
) {
34+
throw new Error(
35+
`"createPubSubConnector" expected "mapSubscriptionsToProps" to be a function`
36+
+ ` or a plain object, instead received: ${mapSubscriptionsToProps}.`
37+
);
38+
}
3039
const shouldMapSubscriptions = Boolean(mapSubscriptionsToProps);
40+
const mapSubscriptionIsFunction = typeof mapSubscriptionsToProps === 'function';
41+
3142
const finalMapPublishToProps = isPlainObject(mapPublishToProps) ?
3243
wrapPublishMethods(mapPublishToProps) :
3344
mapPublishToProps || defaultMapPublishToProps;
3445
const shouldUpdatePublishProps = finalMapPublishToProps.length > 1;
46+
3547
const { withRef = false, ownProps = true } = options || {};
3648

3749
let mappedSubscriptions = {};
@@ -98,6 +110,20 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
98110
}, {});
99111
}
100112

113+
function initSubscriptionFunction(pubSub, subscriptionsFunction, updateSubscriptionProps, getProps) {
114+
// init given function, this invocation will subscribe required actions to
115+
// passed pubSub instance
116+
const applySubscription = subscriptionsFunction(pubSub, updateSubscriptionProps, getProps);
117+
118+
if (typeof applySubscription !== 'function') {
119+
throw new Error(
120+
`'initSubscriptionFunction' expected 'subscriptionsFunction' to return`
121+
+ ` a function. Instead received: ${applySubscription}`
122+
);
123+
}
124+
return applySubscription;
125+
}
126+
101127
function computePublishProps(pubSub, props) {
102128
const { publish } = pubSub;
103129
const publishProps = shouldUpdatePublishProps ?
@@ -130,32 +156,53 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
130156
}
131157

132158
this.pubSub = this.pubSubCore.register(this);
159+
this.mappedSubscriptionProps = {};
133160

134161
if (shouldMapSubscriptions) {
135-
registerMappedSubscriptions(
136-
this.pubSub,
137-
mapSubscriptionsToProps,
138-
(...args) => this.updateSingleMappedSubscription(...args),
139-
() => this.props
140-
);
162+
if (mapSubscriptionIsFunction) {
163+
this.applySubscription = initSubscriptionFunction(
164+
this.pubSub,
165+
mapSubscriptionsToProps,
166+
(...args) => this.updateSingleMappedSubscription(...args),
167+
() => this.props
168+
);
169+
this.mappedSubscriptionProps = this.applySubscription(props);
170+
171+
if (!isPlainObject(this.mappedSubscriptionProps)) {
172+
throw new Error(
173+
`'pubSubConnector' expected an object returned from`
174+
+ ` given .applySubscription() method. Instead received:`
175+
+ ` ${this.mappedSubscriptionProps}`
176+
);
177+
}
178+
} else {
179+
registerMappedSubscriptions(
180+
this.pubSub,
181+
mapSubscriptionsToProps,
182+
(...args) => this.updateSingleMappedSubscription(...args),
183+
() => this.props
184+
);
185+
}
141186
}
142187

143188
this.publishProps = computePublishProps(this.pubSub, props);
144-
this.mappedSubscriptionProps = {};
145189

146190
this.state = {};
147191
}
148192

149193
shouldComponentUpdate(nextProps, nextState) {
150194
const stateChanged = !shallowEqual(nextState, this.state);
151195
const propsChanged = !shallowEqual(nextProps, this.props);
152-
let publishPropsChanged = false;
153196

154197
if (propsChanged && shouldUpdatePublishProps) {
155-
publishPropsChanged = this.updatePublishProps(nextProps);
198+
this.updatePublishProps(nextProps);
156199
}
157200

158-
return propsChanged || stateChanged || publishPropsChanged;
201+
if (propsChanged && shouldMapSubscriptions && mapSubscriptionIsFunction) {
202+
this.updateMappedSubscriptionsProps(nextProps);
203+
}
204+
205+
return propsChanged || stateChanged;
159206
}
160207

161208
componentWillUnmount() {
@@ -182,14 +229,20 @@ export default function createPubSubConnector(mapSubscriptionsToProps, mapPublis
182229
}
183230
}
184231

232+
updateMappedSubscriptionsProps(props = this.props) {
233+
const newValues = this.applySubscription(props);
234+
Object.assign(this.mappedSubscriptionProps, newValues);
235+
cleanEmptyKeys(this.mappedSubscriptionProps);
236+
}
237+
185238
updatePublishProps(props = this.props) {
186239
const nextPublishProps = computePublishProps(this.pubSub, props);
240+
187241
if (shallowEqual(nextPublishProps, this.publishProps)) {
188242
return false;
189243
}
190244

191245
this.publishProps = nextPublishProps;
192-
return true;
193246
}
194247

195248
hasSubscriptions() {

0 commit comments

Comments
 (0)