From b3d89f46efc55275fab90b3f849dbfc0bb7f0f47 Mon Sep 17 00:00:00 2001 From: Jerry Zou Date: Sat, 17 Nov 2018 19:04:54 +0800 Subject: [PATCH] fix(use-observable): store subjects into state directly --- src/use-observable.ts | 60 +++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/use-observable.ts b/src/use-observable.ts index 58c3f2a4..73ef35fe 100644 --- a/src/use-observable.ts +++ b/src/use-observable.ts @@ -1,22 +1,12 @@ -import { Observable, BehaviorSubject, Subject } from 'rxjs' +import { Observable, BehaviorSubject } from 'rxjs' import { useState, useEffect, useMemo } from 'react' -const PREFIX = '__SUBJECT__' - -const propsSubjects: { - [index: string]: Subject | null -} = {} - -let subjectId = 0 - -const concatSubjectKey = (id: number) => `${PREFIX}${id}` - export type InputFactory = U extends undefined ? () => Observable : (props$: Observable) => Observable -export function useObservable(inputFactory: InputFactory): T | null -export function useObservable(inputFactory: InputFactory, initialState: T): T +export function useObservable(inputFactory: InputFactory): T | null +export function useObservable(inputFactory: InputFactory, initialState: T): T export function useObservable>( inputFactory: InputFactory, initialState: T, @@ -28,36 +18,26 @@ export function useObservable | undefined>( initialState?: T, inputs?: U, ): T | null { - const [state, setState] = useState<[T | null, number]>([initialState || null, 0]) - if (inputs) { - useMemo( - () => { - const props$ = propsSubjects[concatSubjectKey(state[1])] - if (props$) { - props$.next(inputs) - } - }, - inputs as ReadonlyArray, - ) - } + const [inputs$] = useState(new BehaviorSubject(inputs)) + const [state, setState] = useState(typeof initialState !== 'undefined' ? initialState : null) + useEffect( () => { - const props$ = new BehaviorSubject(inputs as U) - const input$ = (inputFactory as (...args: any[]) => Observable)( - typeof inputs !== 'undefined' ? props$ : void 0, + const output$ = (inputFactory as (inputs$?: Observable) => Observable)( + typeof inputs !== 'undefined' ? inputs$ : void 0, ) - subjectId++ - const subscription = input$.subscribe((value) => { - setState([value, subjectId]) - }) - const subjectKey = concatSubjectKey(subjectId) - propsSubjects[subjectKey] = props$ - return () => { - subscription.unsubscribe() - propsSubjects[subjectKey] = null - } + const subscription = output$.subscribe((value) => setState(value)) + return () => subscription.unsubscribe() }, - [0], // immutable forever + [], // immutable forever ) - return state[0] + + useMemo( + () => { + inputs$.next(inputs) + }, + (inputs || []) as ReadonlyArray, + ) + + return state }