@@ -64,57 +64,94 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
6464 }
6565
6666 getOptimisticResult ( queries : QueryObserverOptions [ ] ) : QueryObserverResult [ ] {
67- return queries . map ( ( options , index ) => {
68- const defaultedOptions = this . client . defaultQueryObserverOptions ( options )
69- return this . getObserver ( defaultedOptions , index ) . getOptimisticResult (
70- defaultedOptions
71- )
72- } )
67+ return this . findMatchingObservers ( queries ) . map ( match =>
68+ match . observer . getCurrentResult ( )
69+ )
7370 }
7471
75- private getObserver (
76- options : QueryObserverOptions ,
77- index : number
78- ) : QueryObserver {
72+ private findMatchingObservers (
73+ queries : QueryObserverOptions [ ]
74+ ) : QueryObserverMatch [ ] {
75+ const prevObservers = this . observers
76+ const defaultedQueryOptions = queries . map ( options =>
77+ this . client . defaultQueryObserverOptions ( options )
78+ )
79+
80+ const matchingObservers : QueryObserverMatch [ ] = defaultedQueryOptions . flatMap (
81+ defaultedOptions => {
82+ const match = prevObservers . find (
83+ observer => observer . options . queryHash === defaultedOptions . queryHash
84+ )
85+ if ( match != null ) {
86+ return [ { defaultedQueryOptions : defaultedOptions , observer : match } ]
87+ }
88+ return [ ]
89+ }
90+ )
91+
92+ const matchedQueryHashes = matchingObservers . map (
93+ match => match . defaultedQueryOptions . queryHash
94+ )
95+ const unmatchedQueries = defaultedQueryOptions . filter (
96+ defaultedOptions =>
97+ ! matchedQueryHashes . includes ( defaultedOptions . queryHash )
98+ )
99+
100+ const unmatchedObservers = prevObservers . filter (
101+ prevObserver =>
102+ ! matchingObservers . some ( match => match . observer === prevObserver )
103+ )
104+
105+ const newOrReusedObservers : QueryObserverMatch [ ] = unmatchedQueries . map (
106+ ( options , index ) => {
107+ if ( options . keepPreviousData ) {
108+ // return previous data from one of the observers that no longer match
109+ const previouslyUsedObserver = unmatchedObservers [ index ]
110+ if ( previouslyUsedObserver !== undefined ) {
111+ return {
112+ defaultedQueryOptions : options ,
113+ observer : previouslyUsedObserver ,
114+ }
115+ }
116+ }
117+ return {
118+ defaultedQueryOptions : options ,
119+ observer : this . getObserver ( options ) ,
120+ }
121+ }
122+ )
123+
124+ return matchingObservers . concat ( newOrReusedObservers )
125+ }
126+
127+ private getObserver ( options : QueryObserverOptions ) : QueryObserver {
79128 const defaultedOptions = this . client . defaultQueryObserverOptions ( options )
80- let currentObserver = this . observersMap [ defaultedOptions . queryHash ! ]
81- if ( ! currentObserver && defaultedOptions . keepPreviousData ) {
82- currentObserver = this . observers [ index ]
83- }
129+ const currentObserver = this . observersMap [ defaultedOptions . queryHash ! ]
84130 return currentObserver ?? new QueryObserver ( this . client , defaultedOptions )
85131 }
86132
87133 private updateObservers ( notifyOptions ?: NotifyOptions ) : void {
88134 notifyManager . batch ( ( ) => {
89- let hasIndexChange = false
90-
91135 const prevObservers = this . observers
92- const prevObserversMap = this . observersMap
93136
94- const newResult : QueryObserverResult [ ] = [ ]
95- const newObservers : QueryObserver [ ] = [ ]
96- const newObserversMap : Record < string , QueryObserver > = { }
137+ const newObserverMatches = this . findMatchingObservers ( this . queries )
97138
98- this . queries . forEach ( ( options , i ) => {
99- const defaultedOptions = this . client . defaultQueryObserverOptions (
100- options
101- )
102- const queryHash = defaultedOptions . queryHash !
103- const observer = this . getObserver ( defaultedOptions , i )
104-
105- if ( prevObserversMap [ queryHash ] || defaultedOptions . keepPreviousData ) {
106- observer . setOptions ( defaultedOptions , notifyOptions )
107- }
108-
109- if ( observer !== prevObservers [ i ] ) {
110- hasIndexChange = true
111- }
139+ // set options for the new observers to notify of changes
140+ newObserverMatches . forEach ( match =>
141+ match . observer . setOptions ( match . defaultedQueryOptions , notifyOptions )
142+ )
112143
113- newObservers . push ( observer )
114- newResult . push ( observer . getCurrentResult ( ) )
115- newObserversMap [ queryHash ] = observer
116- } )
144+ const newObservers = newObserverMatches . map ( match => match . observer )
145+ const newObserversMap = Object . fromEntries (
146+ newObservers . map ( observer => [ observer . options . queryHash , observer ] )
147+ )
148+ const newResult = newObservers . map ( observer =>
149+ observer . getCurrentResult ( )
150+ )
117151
152+ const hasIndexChange = newObservers . some (
153+ ( observer , index ) => observer !== prevObservers [ index ]
154+ )
118155 if ( prevObservers . length === newObservers . length && ! hasIndexChange ) {
119156 return
120157 }
@@ -157,3 +194,8 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
157194 } )
158195 }
159196}
197+
198+ type QueryObserverMatch = {
199+ defaultedQueryOptions : QueryObserverOptions
200+ observer : QueryObserver
201+ }
0 commit comments