Skip to content

Instantly share code, notes, and snippets.

@JLarky
Created March 5, 2015 06:37
Show Gist options
  • Save JLarky/32767633b5f4a46f8668 to your computer and use it in GitHub Desktop.
Save JLarky/32767633b5f4a46f8668 to your computer and use it in GitHub Desktop.
react.js container helping to subscribe to changes in Flux store written in typescript (es6)
module something {
// inspired by https://github.com/acdlite/flummox/blob/master/docs/api/FluxComponent.md
/* example usage
class SimpleContainer extends FluxSimpleContainer {
stores = {
userStore: App.userStore,
}
getState = () => ({
users: this.stores.userStore.getUsers(),
})
state = this.getState()
render = () => React.DOM.div({},
"There are " + this.state.users.length + " users."
)
}
*/
type subscribable = {
on(event: string, listener: Function): EventEmitter2;
off(event: string, listener: Function): EventEmitter2;
};
type storeDictionary = _.Dictionary<subscribable>;
type emptyObj = {}
export class FluxCompleteContainer<P, S> extends React.Component<P, S> {
private _isMounted = false;
protected stores: {}; // we have to throw types here
getState: () => S;
private subscribeToStores() {
_.each(<storeDictionary>this.stores, (store) => { // restore types
store.on('changed', this.onStoreUpdate);
});
}
private unsubscribeFromStores() {
_.each(<storeDictionary>this.stores, (store) => { // restore types
store.off('changed', this.onStoreUpdate);
});
}
private onStoreUpdate = () => {
var getState = this.getState;
if (getState) {
// to accomodate for case if component is unmounted by the same 'changed' event
if (this._isMounted) {
this.setState(getState());
}
} else {
console.error("getState isn't implmented on ", this);
}
}
constructor(p: P, context: any) {
super(p, context);
var _component = <React.ComponentLifecycle<P, S>> this;
// subscribe
var componentDidMountChild = _component.componentDidMount;
_component.componentDidMount = () => {
this._isMounted = true;
this.subscribeToStores();
componentDidMountChild && componentDidMountChild()
}
// unsubscribe
var componentWillUnmountChild = _component.componentWillUnmount;
_component.componentWillUnmount = () => {
this._isMounted = false;
this.unsubscribeFromStores();
componentWillUnmountChild && componentWillUnmountChild()
}
// pure render mixin
_component.shouldComponentUpdate = React.addons.PureRenderMixin.shouldComponentUpdate;
}
}
export class FluxContainer<P> extends FluxCompleteContainer<P, emptyObj> {}
export class FluxSimpleContainer extends FluxCompleteContainer<emptyObj, emptyObj> {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment