rrr-lazy
Version:
Lazy load component with react && react-router.
89 lines (77 loc) • 2.17 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import hoistNonReactStatics from 'hoist-non-react-statics';
import Lazy from './Lazy';
function interopRequireDefault(obj) {
// eslint-disable-next-line no-underscore-dangle
return obj && obj.__esModule ? obj : { default: obj };
}
function noop() {}
function Empty() {
return null;
}
class LazyDecorated extends React.PureComponent {
constructor(props) {
super(props);
this.handleLoading = this.handleLoading.bind(this);
this.renderComponent = this.renderComponent.bind(this);
this.state = {
Component: null
};
}
handleLoading() {
const { getComponent, lazyProps } = this.props;
const { onLoading = noop } = lazyProps;
return Promise.resolve()
.then(() => getComponent())
.then(c => {
const Component = interopRequireDefault(c).default || Empty;
this.setState({
Component
});
return onLoading();
});
}
renderComponent(status, props) {
const { Component } = this.state;
const { lazyProps } = this.props;
const { render } = lazyProps;
if (typeof render === 'function') {
return render(status, props, Component);
}
if (!Component || status !== 'loaded') return null;
return <Component {...props} />;
}
render() {
const { lazyProps, ownProps } = this.props;
return (
<Lazy
{...ownProps}
{...lazyProps}
render={this.renderComponent}
onLoading={this.handleLoading}
/>
);
}
}
LazyDecorated.propTypes = {
getComponent: PropTypes.func.isRequired,
lazyProps: PropTypes.object.isRequired,
ownProps: PropTypes.object.isRequired
};
const lazy = opts => WrappedComponent => {
const { getComponent, ...lazyProps } = opts;
const Component = ownProps => (
<LazyDecorated
getComponent={
getComponent === 'function' ? getComponent : () => WrappedComponent
}
lazyProps={lazyProps}
ownProps={ownProps}
/>
);
Component.WrappedComponent = WrappedComponent;
hoistNonReactStatics(Component, WrappedComponent);
return Component;
};
export default lazy;