Skip to content

Instantly share code, notes, and snippets.

@7rulnik
Created August 18, 2016 10:48
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save 7rulnik/dee76cdca4fe9fdcee1653ee5b8afb6b to your computer and use it in GitHub Desktop.
/** @jsx React.DOM */
var DeferredComponent,
React = require('react-module'),
ServerNotAvailablePopup = require('kp/util/errorPopupMapper/popups/ServerNotAvailablePopup'),
PreLoader = require('kp/commonWidgets/loaders/PreLoader');
DeferredComponent = React.createClass({
propTypes: {
Connection: React.PropTypes.object.isRequired,
componentName: React.PropTypes.string.isRequired
},
getInitialState: function() {
return {
resolvedComponent: null,
isError: false
};
},
componentDidMount: function() {
this.gotProps(this.props);
},
componentWillReceiveProps: function(newProps) {
this.gotProps(newProps);
},
gotProps: function(props) {
var deferred = this.getComponent(props.componentName);
if (deferred) {
deferred.then(this.onComponentDone, this.onComponentFail);
} else {
this.loadComponent(props.componentName);
}
},
getComponents: function() {
return this.props.Connection.Global.getObject('deferredComponents');
},
getComponent: function(name) {
return this.getComponents()[name];
},
loadComponent: function(name) {
this.setState({ resolvedComponent: null });
var Connection = this.props.Connection,
deferred = Connection.Deferred.defer(),
url = '/components/' + (this.props.isMobile ? 'mobile/' : '') + name.replace(/[A-Z]/g, function(match, index) { return (index > 0 ? '-' : '') + match.toLowerCase() }) + '.js';
deferred.then(this.onComponentDone, this.onComponentFail);
this.getComponents()[name] = deferred;
$
.ajax({
url: url,
cache: !Connection.debug,
dataType: 'script'
})
.done(function() {
// component is resolved by loaded script
})
.fail(function() {
deferred.reject();
});
},
onComponentDone: function(component) {
this.deferIfFailed(function() {
this.isMounted() && this.setState({ resolvedComponent: component });
});
},
onComponentFail: function() {
this.deferIfFailed(function() {
// desktop version fallback
// TODO: implement all mobile version and get rid of it
if (this.props.isMobile) {
window.location.replace(window.location.pathname.replace(this.props.Connection.Config.mobileSitePrefix, ''))
} else {
this.isMounted() && this.setState({ isError: true });
}
});
},
deferIfFailed: function(callback) {
try {
callback.apply(this);
} catch (exception) {
//setTimeout(this.deferIfFailed.bind(null, callback), 500);
console.warn("DeferredComponent: failed", callback, exception);
}
},
onReloadComponent: function() {
this.setState({ isError: false });
this.loadComponent(this.props.componentName);
},
render: function() {
var state = this.state,
props = this.props;
if (state.isError) {
return <ServerNotAvailablePopup onRepeatRequest={this.onReloadComponent} />;
}
if (state.resolvedComponent) {
return state.resolvedComponent(this.props);
}
return props.componentPlaceholder || <PreLoader />;
}
});
module.exports = DeferredComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment