| 64 | } |
| 65 | |
| 66 | function reducerFactory<T>(observable: SuspenseSubject<T>) { |
| 67 | return function reducer(state: ObservableStatus<T>, action: 'value' | 'error' | 'complete'): ObservableStatus<T> { |
| 68 | // always make sure these values are in sync with the observable |
| 69 | const newState = { |
| 70 | ...state, |
| 71 | hasEmitted: state.hasEmitted || observable.hasValue, |
| 72 | error: observable.ourError, |
| 73 | firstValuePromise: observable.firstEmission, |
| 74 | }; |
| 75 | if (observable.hasValue) { |
| 76 | newState.data = observable.value; |
| 77 | } |
| 78 | |
| 79 | switch (action) { |
| 80 | case 'value': |
| 81 | newState.status = 'success'; |
| 82 | return newState; |
| 83 | case 'error': |
| 84 | newState.status = 'error'; |
| 85 | return newState; |
| 86 | case 'complete': |
| 87 | newState.isComplete = true; |
| 88 | return newState; |
| 89 | default: |
| 90 | throw new Error(`invalid action "${action}"`); |
| 91 | } |
| 92 | }; |
| 93 | } |
| 94 | |
| 95 | export function useObservable<T = unknown>(observableId: string, source: Observable<T>, config: ReactFireOptions = {}): ObservableStatus<T> { |
| 96 | // Register the observable with the cache |