import * as React from "react" ; import * as assert from "assert" ; import { Context } from "almin" ; import { shallowEqual } from "shallow-equal-object" ; export type AlminReactContainerDiff < T , U > = T extends U ? never : T ; export type AlminReactContainerObjectDiff < T , U > = Pick < T , AlminReactContainerDiff < keyof T , keyof U > > ; export class AlminReactContainer { static create < T , P > ( WrappedComponent , context ) { if ( process . env . NODE_ENV !== "production" ) { assert . ok ( typeof WrappedComponent === "function" , "WrappedComponent should be React Component Class(Not instance)" ) ; assert . ok ( context instanceof Context , "`context` should be instance of Almin's Context" ) ; } const componentName = WrappedComponent . displayName || WrappedComponent . name ; return class AlminContainer extends React . Component < AlminReactContainerObjectDiff < T , P > > { static displayName = `AlminContainer(${ componentName })` ; state : P ; unSubscribe : ( ) => void | null ; onChangeHandler = ( ) => { this . setState ( context . getState ( ) ) ; } ; constructor ( props ) { super ( props ) ; this . state = context . getState ( ) ; this . unSubscribe = context . onChange ( this . onChangeHandler ) ; } shouldComponentUpdate ( _nextProps , nextState ) { return ! shallowEqual ( this . state , nextState ) ; } componentWillUnmount ( ) { if ( typeof this . unSubscribe === "function" ) { this . unSubscribe ( ) ; } } render ( ) { const C = WrappedComponent as any ; return < C { ... this . state } { ... this . props } />; } } ; } } export default AlminReactContainer ;