@@ -64,57 +64,94 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
64
64
}
65
65
66
66
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
+ )
73
70
}
74
71
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 {
79
128
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 ! ]
84
130
return currentObserver ?? new QueryObserver ( this . client , defaultedOptions )
85
131
}
86
132
87
133
private updateObservers ( notifyOptions ?: NotifyOptions ) : void {
88
134
notifyManager . batch ( ( ) => {
89
- let hasIndexChange = false
90
-
91
135
const prevObservers = this . observers
92
- const prevObserversMap = this . observersMap
93
136
94
- const newResult : QueryObserverResult [ ] = [ ]
95
- const newObservers : QueryObserver [ ] = [ ]
96
- const newObserversMap : Record < string , QueryObserver > = { }
137
+ const newObserverMatches = this . findMatchingObservers ( this . queries )
97
138
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
+ )
112
143
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
+ )
117
151
152
+ const hasIndexChange = newObservers . some (
153
+ ( observer , index ) => observer !== prevObservers [ index ]
154
+ )
118
155
if ( prevObservers . length === newObservers . length && ! hasIndexChange ) {
119
156
return
120
157
}
@@ -157,3 +194,8 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
157
194
} )
158
195
}
159
196
}
197
+
198
+ type QueryObserverMatch = {
199
+ defaultedQueryOptions : QueryObserverOptions
200
+ observer : QueryObserver
201
+ }
0 commit comments