zus
Version:
> a lightweight front-end framework.
89 lines (77 loc) • 2.19 kB
JavaScript
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
}
})
}
render() {
const { AsyncComponent } = this.state
const { LoadingComponent } = this
if (AsyncComponent) return <AsyncComponent {...this.props} />
return <LoadingComponent {...this.props} />
}
}
}
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])
}
const len = models.length
ret.slice(0, len).forEach(m => {
m = m.default || m
if (!Array.isArray(m)) {
m = [m]
}
m.map(_ => registerModel(app, _))
})
return resolve(ret[len])
})
})
},
...config
})
}
dynamic.setDefaultLoadingComponent = LoadingComponent => {
defaultLoadingComponent = LoadingComponent
}