@@ -6,6 +6,53 @@ import { useObservable } from "../internal/useObservable"
66import { SUSPENSE } from "../SUSPENSE"
77import { takeUntilComplete } from "../internal/take-until-complete"
88
9+ class NestedMap < K extends [ ] , V extends Object > {
10+ private root : Map < K , any >
11+ constructor ( ) {
12+ this . root = new Map ( )
13+ }
14+
15+ get ( keys : K [ ] ) : V | undefined {
16+ let current : any = this . root
17+ for ( let i = 0 ; i < keys . length ; i ++ ) {
18+ current = current . get ( keys [ i ] )
19+ if ( ! current ) return undefined
20+ }
21+ return current
22+ }
23+
24+ set ( keys : K [ ] , value : V ) : void {
25+ let current : Map < K , any > = this . root
26+ let i
27+ for ( i = 0 ; i < keys . length - 1 ; i ++ ) {
28+ const key = keys [ i ]
29+ let nextCurrent = current . get ( key )
30+ if ( ! nextCurrent ) {
31+ nextCurrent = new Map < K , any > ( )
32+ current . set ( key , nextCurrent )
33+ }
34+ current = nextCurrent
35+ }
36+ current . set ( keys [ i ] , value )
37+ }
38+
39+ delete ( keys : K [ ] ) : void {
40+ const maps : Map < K , any > [ ] = [ this . root ]
41+ let current : Map < K , any > = this . root
42+
43+ for ( let i = 0 ; i < keys . length - 1 ; i ++ ) {
44+ maps . push ( ( current = current . get ( keys [ i ] ) ) )
45+ }
46+
47+ let mapIdx = maps . length - 1
48+ maps [ mapIdx ] . delete ( keys [ mapIdx ] )
49+
50+ while ( -- mapIdx > - 1 && maps [ mapIdx ] . get ( keys [ mapIdx ] ) . size === 0 ) {
51+ maps [ mapIdx ] . delete ( keys [ mapIdx ] )
52+ }
53+ }
54+ }
55+
956/**
1057 * Accepts: A factory function that returns an Observable.
1158 *
@@ -28,30 +75,28 @@ import { takeUntilComplete } from "../internal/take-until-complete"
2875 * subscription, then the hook will leverage React Suspense while it's waiting
2976 * for the first value.
3077 */
31- export default function connectFactoryObservable <
32- A extends ( number | string | boolean | null ) [ ] ,
33- O
34- > (
78+ const emptyInput = [ 0 ]
79+ export default function connectFactoryObservable < A extends [ ] , O > (
3580 getObservable : ( ...args : A ) => Observable < O > ,
3681 unsubscribeGraceTime : number ,
3782) : [
3883 ( ...args : A ) => Exclude < O , typeof SUSPENSE > ,
3984 ( ...args : A ) => Observable < O > ,
4085] {
41- const cache = new Map < string , [ Observable < O > , BehaviorObservable < O > ] > ( )
86+ const cache = new NestedMap < A , [ Observable < O > , BehaviorObservable < O > ] > ( )
4287
4388 const getSharedObservables$ = (
44- ... input : A
89+ input : A ,
4590 ) : [ Observable < O > , BehaviorObservable < O > ] => {
46- const key = JSON . stringify ( input )
47- const cachedVal = cache . get ( key )
91+ const keys = input . length > 0 ? input : ( emptyInput as A )
92+ const cachedVal = cache . get ( keys )
4893
4994 if ( cachedVal !== undefined ) {
5095 return cachedVal
5196 }
5297
5398 const sharedObservable$ = shareLatest ( getObservable ( ...input ) , ( ) => {
54- cache . delete ( key )
99+ cache . delete ( keys )
55100 } )
56101
57102 const reactObservable$ = reactEnhancer (
@@ -64,12 +109,12 @@ export default function connectFactoryObservable<
64109 reactObservable$ ,
65110 ]
66111
67- cache . set ( key , result )
112+ cache . set ( keys , result )
68113 return result
69114 }
70115
71116 return [
72- ( ...input : A ) => useObservable ( getSharedObservables$ ( ... input ) [ 1 ] ) ,
73- ( ...input : A ) => getSharedObservables$ ( ... input ) [ 0 ] ,
117+ ( ...input : A ) => useObservable ( getSharedObservables$ ( input ) [ 1 ] ) ,
118+ ( ...input : A ) => getSharedObservables$ ( input ) [ 0 ] ,
74119 ]
75120}
0 commit comments