Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<AsyncComponent> at Airbnb used for Webpack code splitting
// Usage:
//
// function loader() {
// return new Promise((resolve) => {
// if (process.env.LAZY_LOAD) {
// require.ensure([], (require) => {
// resolve(require('./SomeComponent').default);
// });
// }
// });
// }
// ...
// <AsyncComponent loader={loader} />
//
// In the future, loader() could be:
// const loader = () => import('./SomeComponent');
import React, { PropTypes } from 'react';
import Spinner from './Spinner';
import { withStyles, css } from '../themes/withStyles';
function DefaultPlaceholder({ height = 300, styles }) {
return (
<div {...css(styles.container, { height })}>
<Spinner />
</div>
);
}
const WrappedPlaceholder = withStyles(({ color }) => ({
container: {
backgroundColor: color.white,
},
}))(DefaultPlaceholder);
DefaultPlaceholder.propTypes = {
height: PropTypes.number,
styles: PropTypes.shape({
backgroundColor: PropTypes.string,
}),
};
export { WrappedPlaceholder };
export default class AsyncComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
Component: null,
};
}
componentDidMount() {
this.props.loader().then((Component) => {
this.setState({ Component });
});
}
render() {
const { Component } = this.state;
const { renderPlaceholder, placeholderHeight } = this.props;
if (Component) {
return <Component {...this.props} />;
}
return renderPlaceholder ?
renderPlaceholder() :
<WrappedPlaceholder height={placeholderHeight} />;
}
}
AsyncComponent.propTypes = {
// specifically loader is a function that returns a promise. The promise
// should resolve to a renderable React component.
loader: PropTypes.func.isRequired,
placeholderHeight: PropTypes.number,
renderPlaceholder: PropTypes.func,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.