import { useState , useMemo } from 'react' ; import { Observable } from 'rxjs/internal/Observable' ; import { Subject } from 'rxjs/internal/Subject' ; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject' ; import { useRx } from './use-rx' ; import { MutableObserver } from './mutable-observer' ; param subject$ export function hasNext < T > ( subject$ ) { return typeof ( subject$ as Subject < T > ) . next !== 'undefined' ; } param observable$ export const UNSET_VALUE = { } ; export function initialObservableValue < T > ( observable$ ) { let initialValue = UNSET_VALUE ; observable$ . subscribe ( val => { initialValue = val ; } ) . unsubscribe ( ) ; return initialValue ; } interface RxConfig < V , S > { isSubject : boolean ; initVal : V ; hadInitVal : boolean ; isNext : boolean ; nextValue ? : ( value ? : V ) => void ; observer : MutableObserver < S > ; } function createRxConfig < S extends Observable < any > | Subject < any > | BehaviorSubject < any > > ( subject$ ) { const initVal = initialObservableValue ( subject$ ) ; const hadInitVal = initVal !== UNSET_VALUE ; const isSubject = hasNext ( subject$ ) ; const nextValue = isSubject ? ( subject$ as Subject < any > ) . next . bind ( subject$ ) : undefined ; const observer = new MutableObserver < S > ( ) ; return { isSubject , initVal , hadInitVal , isNext : ! hadInitVal , nextValue , observer } ; } param subject$ export function useRxState < S extends Observable < any > | Subject < any > | BehaviorSubject < any > > ( subject$ ) { const initObj = useMemo ( ( ) => createRxConfig ( subject$ ) , [ subject$ ] ) ; const [ value , setValue ] = useState ( ( ) => ( initObj . hadInitVal ? initObj . initVal : undefined ) ) ; initObj . observer . setNext ( nextValue => { if ( initObj . isNext ) { setValue ( nextValue ) ; } else { initObj . isNext = true ; delete initObj . initVal ; } } ) ; useRx ( subject$ , initObj . observer ) ; return [ value , initObj . nextValue ] as any ; } param observable$ export function useRxStateResult < T > ( observable$ ) { const [ value ] = useRxState ( observable$ ) ; return value ; } /**
 * `useRxStateAction`
 *
 * For a given subject returns a set function.
 *
 * Example:
 * const setName = useRxStateResult(name$);
 */ export function useRxStateAction < T > ( subject$ ) { const next = useMemo ( ( ) => subject$ . next . bind ( subject$ ) , [ subject$ ] ) ; return next ; }