reactive-di
Version:
Reactive dependency injection
76 lines (66 loc) • 2.46 kB
JavaScript
// @flow
import {createConnect, CatchableComponent} from 'urc'
import type {IReactHost, IReactAtom, IRenderError, ErrorProps} from 'urc'
import Injector from './Injector'
import type {IRenderFn} from './interfaces'
export default function createReactWrapper<IElement>(
BaseComponent: Class<*>,
renderError: IRenderError<IElement, *>,
ReactAtom: Class<IReactAtom<IElement>>,
rootInjector?: Injector = new Injector(),
) {
const names: Map<string, number> = new Map()
function normalizeClass<A: {displayName: string}>(cls: A): A {
let prefix = names.get(cls.displayName)
if (prefix !== undefined) {
prefix++
names.set(cls.displayName, prefix)
cls.displayName = cls.displayName + prefix
} else {
names.set(cls.displayName, 0)
}
return cls
}
class MixinComponent<Props: Object, State, Context> extends CatchableComponent<Props, State, Context, IElement> {
_injector: Injector
static instance: number
props: Props
componentWillMount() {
super.componentWillMount()
const cns: Function = this.constructor
if (cns.instance === undefined) {
cns.instance = 0
cns.isDynamic = false
}
cns.instance++
let injector: Injector = rootInjector
const props = this.props
if (props && props.__lom_ctx !== undefined) injector = props.__lom_ctx
this._injector = injector.copy(cns)
this._injector.id = cns.displayName
this._injector.props = props
}
componentWillUnmount() {
this.constructor.instance--
this._injector.destructor()
super.componentWillUnmount()
}
__value(isPropsChanged: boolean) {
const oldInjector = Injector.parentContext
Injector.parentContext = this._injector
const value = super.__value(isPropsChanged)
Injector.parentContext = oldInjector
return value
}
_getContext(key: Function, propsChanged: boolean): Context {
return this._injector.getContext(key, propsChanged ? this.props : undefined)
}
}
return ((createConnect({
ReactAtom,
renderError,
BaseComponent,
MixinComponent,
normalizeClass
}): any): IRenderFn<*, *>)
}