Skip to content

Instantly share code, notes, and snippets.

@petyappetrov
Created November 21, 2016 07:43
Show Gist options
  • Save petyappetrov/aac51bcd76751e627674f0ec63d2d98e to your computer and use it in GitHub Desktop.
Save petyappetrov/aac51bcd76751e627674f0ec63d2d98e to your computer and use it in GitHub Desktop.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2016 Quantron Systems LLC.
// All Rights Reserved.
//
// This file is part of the Pakmil project.
// For conditions of distribution and use,
// please contact sales@quantron-systems.com
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import React from 'react';
import _ from 'lodash';
import {getStores, getStoreValues} from './storeDeclarations';
import EventListenHelper from '../common/EventListenHelper';
const inBrowser = typeof window !== 'undefined';
const isDevMode = process.env.NODE_ENV !== 'production';
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
export default function bindStores(storeDeclarations, Component, LoadingComponent) {
return React.createClass({
displayName: `bindStores(${Component.displayName})`,
statics: {
getStoreDeclarations() {
return storeDeclarations;
},
getChildComponents() {
return _.compact([Component, LoadingComponent]);
}
},
contextTypes: {
storeManager: React.PropTypes.object
},
getStoreManager() {
if(!this.context.storeManager) throw new Error('Store manager not found');
return this.context.storeManager;
},
onStoreChanged() {
this.setState({stores: this.stores});
},
getStores(props, acquire) {
return getStores(this.getStoreManager(), storeDeclarations, acquire, props);
},
getInitialState() {
this.stores = this.getStores(this.props, false);
return {stores: this.stores};
},
componentDidMount() {
this.eventHelper = new EventListenHelper();
this.stores = this.getStores(this.props, true);
_.each(this.stores, store => {
this.eventHelper.add(store, 'changed', this.onStoreChanged);
if(!store.loaded) store.load();
});
this.setState({stores: this.stores});
},
componentWillReceiveProps(newProps) {
const storeManager = this.getStoreManager();
const newStores = this.getStores(newProps, true);
let hasChange = false;
_.each(newStores, (newStore, name) => {
if(!newStore.loaded) newStore.load();
const oldStore = this.stores[name];
if(newStore != oldStore) {
hasChange = true;
this.eventHelper.add(newStore, 'changed', this.onStoreChanged);
if(oldStore) {
this.eventHelper.remove(oldStore);
storeManager.releaseStore(oldStore);
}
} else if(oldStore) {
storeManager.releaseStore(oldStore);
}
});
const newKeys = _.keys(newStores);
const missedStores = _.pickBy(
this.stores,
(store, key) => !_.includes(newKeys, key)
);
if(!_.isEmpty(missedStores)) {
_.each(missedStores, store => {
this.eventHelper.remove(store);
storeManager.releaseStore(store);
});
hasChange = true;
}
if(hasChange) {
this.stores = newStores;
this.setState({stores: newStores});
}
},
componentWillUnmount() {
const storeManager = this.getStoreManager();
_.each(this.stores, (store) => {
storeManager.releaseStore(store);
});
this.eventHelper.removeAll();
},
render() {
const valueProps = getStoreValues(this.stores);
const allLoaded = _.every(this.stores, store => store && store.loaded);
if(isDevMode && !inBrowser && !allLoaded) {
const declaration = _.isFunction(storeDeclarations) ? storeDeclarations(this.props) : storeDeclarations;
console.warn(
'Server Side rendering: possibly not loaded data in',
`<${Component.displayName} />, declaration: \n\r`,
JSON.stringify(declaration));
}
if(!allLoaded && LoadingComponent) {
if(_.isBoolean(LoadingComponent)) return null;
return <LoadingComponent {...valueProps} {...this.props}/>;
}
return <Component stores={this.stores} {...this.props} {...valueProps}/>;
}
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment