import * as React from 'react' ; import { observer } from 'mobx-react' ; import { IView , IViewProps , IComponentProps , IViewModel , IComponentDefinition , IComponentState , ILinkDisposer } from './interfaces/index' ; import { createLink } from './createLink' ; import { createModel } from './createModel' ; import { disposeModel } from './disposeModel' ; export function createComponent < TComponentProps > ( definition ) { const { view , displayName = 'UnnamedComponent' } = definition ; if ( ! view ) { throw "[mobx-mvvm] ERROR! view should be provided in order to create a component!" ; } return ( ViewModel ) : React . ComponentClass < TComponentProps & IComponentProps < IViewModel > > => { type TProps = TComponentProps & IComponentProps < IViewModel > ; const ObserverComponent = observer ( view as React . StatelessComponent < TProps > ) ; class NewComponent extends React . Component < TProps , IComponentState > { linkDisposer : ILinkDisposer = null ; state : IComponentState = { model : null , shouldDispose : false } ; constructor ( props , ctx ) { super ( props , ctx ) ; this . state = createModel ( this . state , props , ctx , ViewModel ) ; this . linkDisposer = createLink ( this . state , props , definition ) ; } componentWillReceiveProps ( newProps ) { if ( this . linkDisposer ) this . linkDisposer ( ) ; const newState = createModel ( this . state , newProps , this . context , ViewModel ) ; this . linkDisposer = createLink ( newState , newProps , definition ) ; } componentWillUnmount ( ) { if ( this . linkDisposer ) this . linkDisposer ( ) ; if ( this . props . modelRef ) { this . props . modelRef ( null ) ; } disposeModel ( this . state ) ; } render ( ) { return React . createElement ( ObserverComponent , Object . assign ( { } , this . props , { model : this . state . model } ) , this . props . children ) ; } } const NewComponentClass = NewComponent as React . ComponentClass < TComponentProps & IComponentProps < IViewModel > > ; NewComponentClass . displayName = displayName ; NewComponentClass . contextTypes = { resolver : React . PropTypes . any } ; return NewComponentClass ; } ; }