From 87f41c848d8af2b0b2d2fe35c5ebb14278d9a3e6 Mon Sep 17 00:00:00 2001 From: Josep M Sobrepere Date: Tue, 9 Jun 2020 20:54:59 +0200 Subject: [PATCH] ditch connectInstanceObservable --- src/connectInstanceObservable.ts | 112 ------------------------ src/index.tsx | 1 - test/connectInstanceObservable.test.ts | 114 ------------------------- 3 files changed, 227 deletions(-) delete mode 100644 src/connectInstanceObservable.ts delete mode 100644 test/connectInstanceObservable.test.ts diff --git a/src/connectInstanceObservable.ts b/src/connectInstanceObservable.ts deleted file mode 100644 index 2d7ae96..0000000 --- a/src/connectInstanceObservable.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { Observable, BehaviorSubject } from "rxjs" -import { FactoryObservableOptions } from "./options" -import { map } from "rxjs/operators" -import { useEffect, useRef, useState } from "react" -import delayUnsubscription from "./operators/delay-unsubscription" -import { distinctShareReplay, BehaviorObservable } from "./" - -interface ConnectInstanceObservable { - ( - getObservable: (props$: Observable<[T1, T2]>) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2) => O | I - ( - getObservable: (props$: Observable<[T1, T2, T3]>) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3) => O | I - ( - getObservable: (props$: Observable<[T1, T2, T3, T4]>) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4) => O | I - ( - getObservable: (props$: Observable<[T1, T2, T3, T4, T5]>) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4, e: T5) => O | I - ( - getObservable: ( - props$: Observable<[T1, T2, T3, T4, T5, T6]>, - ) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6) => O | I - ( - getObservable: ( - props$: Observable<[T1, T2, T3, T4, T5, T6, T7]>, - ) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7) => O | I - ( - getObservable: ( - props$: Observable<[T1, T2, T3, T4, T5, T6, T7, T8]>, - ) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8) => O | I - ( - getObservable: ( - props$: Observable<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>, - ) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, i: T9) => O | I - ( - getObservable: (props$: Observable) => Observable, - initialValue: I, - options?: FactoryObservableOptions, - ): (a: T1) => O | I -} - -const flatSingleTuple = (src: Observable>) => - map((inputs: any) => (inputs.length === 1 ? inputs[0] : inputs))(src) - -const cache = new WeakMap< - React.MutableRefObject, - BehaviorObservable ->() - -const defaultValue: any = {} -export const connectInstanceObservable: ConnectInstanceObservable = ( - getObservable: any, - unsubscribeGraceTime = 200, -) => { - const getSuspendedState = (ref: React.MutableRefObject, input: any) => { - let source$ = cache.get(ref) - if (source$) { - return source$.getValue() - } - - const subject = new BehaviorSubject(input) - ref.current = subject - source$ = delayUnsubscription(unsubscribeGraceTime)( - distinctShareReplay()(subject.pipe(flatSingleTuple, getObservable)), - ) - cache.set(ref, source$) - return source$.getValue() - } - - const useInstance = (...input: any) => { - const subjectRef = useRef() - const [state, setState] = useState(defaultValue) - - useEffect(() => { - const subscription = cache.get(subjectRef)!.subscribe(setState) - return () => subscription.unsubscribe() - }, []) - - useEffect(() => { - if (subjectRef.current!.i) { - subjectRef.current!.next(input) - } - subjectRef.current!.i = 1 - }, input) - - return state !== defaultValue ? state : getSuspendedState(subjectRef, input) - } - - return useInstance as any -} diff --git a/src/index.tsx b/src/index.tsx index 554920d..0c3c1e6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,5 @@ export { connectObservable } from "./connectObservable" export { connectFactoryObservable } from "./connectFactoryObservable" -export { connectInstanceObservable } from "./connectInstanceObservable" export { default as distinctShareReplay, BehaviorObservable, diff --git a/test/connectInstanceObservable.test.ts b/test/connectInstanceObservable.test.ts deleted file mode 100644 index ad790af..0000000 --- a/test/connectInstanceObservable.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { connectInstanceObservable } from "../src" -import { of, Subject, Observable, combineLatest, merge } from "rxjs" -import { renderHook, act } from "@testing-library/react-hooks" -import { - ignoreElements, - switchMap, - distinctUntilChanged, - scan, - shareReplay, - tap, - map, - startWith, -} from "rxjs/operators" -import { groupInMap } from "@josepot/rxjs-utils" - -const getPriceData = (key: string, period: number) => - of( - key - .split("") - .map((_, idx) => idx) - .concat(period), - ) - -const tagAndPeriod$ = new Subject<[string, number]>() -const tagsData$ = tagAndPeriod$.pipe( - groupInMap( - ([tag]) => tag, - stream$ => - stream$.pipe( - scan((maxPeriod, [, period]) => Math.max(maxPeriod, period), 0), - distinctUntilChanged(), - switchMap(period => getPriceData(stream$.key, period)), - ), - ), - startWith(new Map()), - shareReplay(1), -) -const empty: number[] = [] -const usePriceData = connectInstanceObservable( - (props$: Observable<[string, number]>) => { - const plug$ = props$.pipe(tap(tagAndPeriod$), ignoreElements()) - - const data$ = props$.pipe( - map(([tag]) => tag), - distinctUntilChanged(), - switchMap(tag => - tagsData$.pipe( - map(tags => tags.get(tag) || empty), - distinctUntilChanged(), - ), - ), - ) - - const periods$ = props$.pipe( - map(([, period]) => period), - distinctUntilChanged(), - ) - - return merge(combineLatest(data$, periods$), plug$).pipe( - map(([data, period]) => data.slice(-period)), - ) as Observable - }, - [], -) - -describe("connectInstanceObservable", () => { - it("works", () => { - const { result, rerender } = renderHook( - ({ tag, period }: { tag: string; period: number }) => - usePriceData(tag, period), - { initialProps: { tag: "hello", period: 9 } }, - ) - - expect(result.current).toEqual([0, 1, 2, 3, 4, 9]) - - act(() => { - rerender({ tag: "hello", period: 2 }) - }) - - expect(result.current).toEqual([4, 9]) - - act(() => { - rerender({ tag: "ups", period: 8 }) - }) - - expect(result.current).toEqual([0, 1, 2, 8]) - - act(() => { - rerender({ tag: "012345", period: 10 }) - }) - - expect(result.current).toEqual([0, 1, 2, 3, 4, 5, 10]) - }) - - it("also works with one argument", () => { - const useDoubles = connectInstanceObservable( - (props$: Observable) => props$.pipe(map(x => x * 2)), - null, - ) - - const { result, rerender } = renderHook( - ({ input }: { input: number }) => useDoubles(input), - { initialProps: { input: 1 } }, - ) - - expect(result.current).toEqual(2) - - act(() => { - rerender({ input: 2 }) - }) - - expect(result.current).toEqual(4) - }) -})