Skip to content

Instantly share code, notes, and snippets.

@dpoindexter
Created December 28, 2015 17:44
Show Gist options
  • Save dpoindexter/11f87aa7d00213a3d441 to your computer and use it in GitHub Desktop.
Save dpoindexter/11f87aa7d00213a3d441 to your computer and use it in GitHub Desktop.
React component mixin for declarative side effects
class Update {
constructor (state) {
this.newState = state;
this.effects = [];
}
state (update) {
this.newState = { ...this.newState, update };
}
effect (fn) {
this.effects.push(fn);
}
}
function assertHasUpdateMethod (component) {
utils.assert(
utils.isFunction(component.update),
`withUpdates requires ${component.displayName} to implement an 'update' method`
);
}
function assertIsThenable (thenable, componentName) {
utils.assert(
thenable.then && utils.isFunction(thenable.then),
`Scheduled effects must return thenables. Check the 'update' method of ${componentName}`
);
}
function effectsMixinForChannel (channel) {
return {
componentWillMount () {
this.schedule(this.props, null, false);
},
componentWillReceiveProps (nextProps) {
this.schedule(this.props, nextProps, true);
},
schedule (props, nextProps, isMounted) {
assertHasUpdateMethod(this);
const update = this.update(this.props, nextProps, new Update(this, channel), true);
// Syncronously handle state updates
this.setState(update.newState);
// Schedule eventual updates
this.effects.forEach((effect) => {
const thenable = effect();
assertIsThenable(thenable, component.displayName);
thenable.then(this.applyEffect, this.applyEffect);
});
},
applyEffect (actionOrUpdate, ...additionalData) {
// Promise returns either a string constant Action...
if (utils.isString(actionOrUpdate)) {
channel.publish(actionOrUpdate, { additionalData });
}
// ...or an object to merge into component state
if (utils.isObject(actionOrUpdate)) {
this.setState(actionOrUpdate);
}
}
};
}
export { effectsMixinForChannel };
// default effects mixin publishes on default channel
export default effectsMixinForChannel();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment