Skip to content

Instantly share code, notes, and snippets.

@glortho
Created October 15, 2015 15:33
Show Gist options
  • Save glortho/458bc65fee43fb9873e1 to your computer and use it in GitHub Desktop.
Save glortho/458bc65fee43fb9873e1 to your computer and use it in GitHub Desktop.
Decorator/higher-order React component for binding view-controllers to stores in Flux pattern
import React from 'react';
import autobind from 'autobind-decorator';
// Note: Assumes stores have a unique `key` prop and a `getState()` method
function listenTo( stores = [] ) {
const storesArray = [].concat( stores );
return function listenToDecorator( WrappedComponent ) {
class StoreListener extends React.Component {
constructor( props ) {
super( props );
this.state = storesArray.reduce( ( memo, { key, getState } ) => {
memo[ key ] = getState();
return memo;
}, {} );
}
componentDidMount() {
this._bindings = new Map();
// loop through stores being listened to and add change listeners to each.
// store these bindings in an array so that they can be unbound on unmount.
storesArray.forEach( store => {
const listener = this._onChange.bind( this, store );
store.addChangeListener( listener );
this._bindings.set( store, listener );
});
}
componentWillUnmount() {
if ( this._bindings.size ) {
this._bindings.forEach( ( listener, store ) => store.removeChangeListener( listener ) );
this._bindings.clear();
}
}
@autobind
_onChange( store ) {
this.setState( { [ store.key ]: store.getState() } );
}
render() {
return <WrappedComponent {...this.props} {...this.state} />;
}
}
return StoreListener;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment