import React, { Component } from 'react'; const cached = {}; function registerModel(app, model) { model = model.default || model; if (!cached[model.namespace]) { app.model(model); cached[model.namespace] = 1; } } let defaultLoadingComponent = () => null; function asyncComponent(config) { const { resolve } = config; return class DynamicComponent extends Component { constructor(...args) { super(...args); this.LoadingComponent = config.LoadingComponent || defaultLoadingComponent; this.state = { AsyncComponent: null, }; this.load(); } componentDidMount() { this.mounted = true; } componentWillUnmount() { this.mounted = false; } load() { resolve().then(m => { const AsyncComponent = m.default || m; if (this.mounted) { this.setState({ AsyncComponent }); } else { this.state.AsyncComponent = AsyncComponent; // eslint-disable-line } }); } render() { const { AsyncComponent } = this.state; const { LoadingComponent } = this; if (AsyncComponent) return ; return ; } }; } export default function dynamic(config) { const { app, models: resolveModels, component: resolveComponent } = config; return asyncComponent({ resolve: config.resolve || function() { const models = typeof resolveModels === 'function' ? resolveModels() : []; const component = resolveComponent(); return new Promise(resolve => { Promise.all([...models, component]).then(ret => { if (!models || !models.length) { return resolve(ret[0]); } else { const len = models.length; ret.slice(0, len).forEach(m => { m = m.default || m; if (!Array.isArray(m)) { m = [m]; } m.map(_ => registerModel(app, _)); }); resolve(ret[len]); } }); }); }, ...config, }); } dynamic.setDefaultLoadingComponent = LoadingComponent => { defaultLoadingComponent = LoadingComponent; };