Skip to content

Instantly share code, notes, and snippets.

@andrey-kazakov
Last active August 29, 2015 14:27
Show Gist options
  • Save andrey-kazakov/ea410bea880d84639edc to your computer and use it in GitHub Desktop.
Save andrey-kazakov/ea410bea880d84639edc to your computer and use it in GitHub Desktop.
It's a solution to asynchronously load React components used internally in our project. It has a quite simple logic, so just read the script and use it as you want. It depends on jQuery.ajax and jQuery.Deferred, but you can easily avoid it. Loaded script should just do `window.deferredComponents['YourReactComponent'].resolve(YourReactComponent)`
var DeferredComponent;
DeferredComponent = React.createClass({
propTypes: {
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 (window.deferredComponents = (window.deferredComponents || {}));
},
getComponent: function(name) {
return this.getComponents()[name];
},
loadComponent: function(name) {
this.setState({ resolvedComponent: null });
var deferred = $.Deferred(),
url = '/components/' + 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: true, // use false in debug environment
dataType: 'script'
})
.done(function() {
// component is resolved by loaded script
})
.fail(function() {
deferred.reject();
});
},
onComponentDone: function(component) {
this.isMounted() && this.setState({ resolvedComponent: component });
},
onComponentFail: function() {
this.isMounted() && this.setState({ isError: true });
},
onReloadComponent: function() {
this.setState({ isError: false });
this.loadComponent(this.props.componentName);
},
render: function() {
var state = this.state,
props = this.props;
if (state.isError) {
return props.failedComponentPlaceholder;
}
if (state.resolvedComponent) {
return state.resolvedComponent(this.props);
}
return props.componentPlaceholder;
}
});
module.exports = DeferredComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment