import * as React from 'react' ; import { Observable , Subscription } from 'rxjs' ; import { shallowEqual } from './shallowEqual' ; const initialValue = Symbol . for ( 'initialValue' ) ; interface Props < T > { readonly props ? : any [ ] ; readonly createStream : ( ) => Observable < T > ; readonly children : ( props : T ) => React . ReactNode ; } interface State < T > { readonly value : T | typeof initialValue ; } example export class FromStream < T > extends React . Component < Props < T > , State < T > > { public state : State < T > ; private mutableSubscription : Subscription | undefined ; private mutableMounted = false ; public constructor ( props ) { super ( props ) ; this . state = { value : initialValue } ; this . subscribe ( ) ; this . mutableMounted = true ; } public componentWillUnmount ( ) { this . mutableMounted = false ; this . unsubscribe ( ) ; } public componentDidUpdate ( prevProps ) { const props = this . props ; if ( ( prevProps . props != undefined && props . props == undefined ) || ( prevProps . props == undefined && props . props != undefined ) || ( prevProps . props != undefined && props . props != undefined && ( prevProps . props . length !== props . props . length || prevProps . props . some ( ( propA , idx ) => ! shallowEqual ( propA , props . props [ idx ] ) ) ) ) ) { this . subscribe ( ) ; } } public render ( ) { const { value } = this . state ; if ( value === initialValue ) { return null ; } return this . props . children ( value ) ; } private subscribe ( ) { this . unsubscribe ( ) ; let stateSet = false ; this . mutableSubscription = this . props . createStream ( ) . subscribe ( { next : ( value ) => { stateSet = true ; this . _setValue ( value ) ; } } ) ; if ( ! stateSet ) { this . _setValue ( initialValue ) ; } } private _setValue ( value ) { if ( this . mutableMounted ) { this . setState ( { value } ) ; } else { this . state = { value } ; } } private unsubscribe ( ) { if ( this . mutableSubscription !== undefined ) { this . mutableSubscription . unsubscribe ( ) ; this . mutableSubscription = undefined ; } } }