@@ -87,6 +87,7 @@ export class QueryObserver<
87
87
this . executeFetch ( )
88
88
}
89
89
90
+ this . updateResult ( )
90
91
this . updateTimers ( )
91
92
}
92
93
}
@@ -155,7 +156,6 @@ export class QueryObserver<
155
156
options ?: QueryObserverOptions < TQueryFnData , TError , TData , TQueryData >
156
157
) : void {
157
158
const prevOptions = this . options
158
- const prevQuery = this . currentQuery
159
159
160
160
this . options = this . client . defaultQueryObserverOptions ( options )
161
161
@@ -171,39 +171,60 @@ export class QueryObserver<
171
171
this . options . queryKey = prevOptions . queryKey
172
172
}
173
173
174
- this . updateQuery ( )
174
+ const didUpdateQuery = this . updateQuery ( )
175
175
176
- // Take no further actions if there are no subscribers
177
- if ( ! this . listeners . length ) {
178
- return
179
- }
176
+ let optionalFetch
177
+ let updateStaleTimeout
178
+ let updateRefetchInterval
180
179
181
- // If we subscribed to a new query, optionally fetch and update refetch
182
- if ( this . currentQuery !== prevQuery ) {
183
- this . optionalFetch ( )
184
- this . updateTimers ( )
185
- return
180
+ // If we subscribed to a new query, optionally fetch and update intervals
181
+ if ( didUpdateQuery ) {
182
+ optionalFetch = true
183
+ updateStaleTimeout = true
184
+ updateRefetchInterval = true
186
185
}
187
186
188
187
// Optionally fetch if the query became enabled
189
188
if ( this . options . enabled !== false && prevOptions . enabled === false ) {
190
- this . optionalFetch ( )
189
+ optionalFetch = true
191
190
}
192
191
193
192
// Update stale interval if needed
194
193
if (
195
194
this . options . enabled !== prevOptions . enabled ||
196
195
this . options . staleTime !== prevOptions . staleTime
197
196
) {
198
- this . updateStaleTimeout ( )
197
+ updateStaleTimeout = true
199
198
}
200
199
201
200
// Update refetch interval if needed
202
201
if (
203
202
this . options . enabled !== prevOptions . enabled ||
204
203
this . options . refetchInterval !== prevOptions . refetchInterval
205
204
) {
206
- this . updateRefetchInterval ( )
205
+ updateRefetchInterval = true
206
+ }
207
+
208
+ // Fetch only if there are subscribers
209
+ if ( this . hasListeners ( ) ) {
210
+ if ( optionalFetch ) {
211
+ this . optionalFetch ( )
212
+ }
213
+ }
214
+
215
+ // Update result when subscribing to a new query
216
+ if ( didUpdateQuery ) {
217
+ this . updateResult ( )
218
+ }
219
+
220
+ // Update intervals only if there are subscribers
221
+ if ( this . hasListeners ( ) ) {
222
+ if ( updateStaleTimeout ) {
223
+ this . updateStaleTimeout ( )
224
+ }
225
+ if ( updateRefetchInterval ) {
226
+ this . updateRefetchInterval ( )
227
+ }
207
228
}
208
229
}
209
230
@@ -302,12 +323,7 @@ export class QueryObserver<
302
323
303
324
this . staleTimeoutId = setTimeout ( ( ) => {
304
325
if ( ! this . currentResult . isStale ) {
305
- const prevResult = this . currentResult
306
326
this . updateResult ( )
307
- this . notify ( {
308
- listeners : this . shouldNotifyListeners ( prevResult , this . currentResult ) ,
309
- cache : true ,
310
- } )
311
327
}
312
328
} , timeout )
313
329
}
@@ -353,9 +369,7 @@ export class QueryObserver<
353
369
this . refetchIntervalId = undefined
354
370
}
355
371
356
- protected getNewResult (
357
- willFetch ?: boolean
358
- ) : QueryObserverResult < TData , TError > {
372
+ protected getNewResult ( ) : QueryObserverResult < TData , TError > {
359
373
const { state } = this . currentQuery
360
374
let { isFetching, status } = state
361
375
let isPreviousData = false
@@ -364,7 +378,7 @@ export class QueryObserver<
364
378
let dataUpdatedAt = state . dataUpdatedAt
365
379
366
380
// Optimistically set status to loading if we will start fetching
367
- if ( willFetch ) {
381
+ if ( ! this . hasListeners ( ) && this . willFetchOnMount ( ) ) {
368
382
isFetching = true
369
383
if ( ! dataUpdatedAt ) {
370
384
status = 'loading'
@@ -442,7 +456,7 @@ export class QueryObserver<
442
456
}
443
457
444
458
private shouldNotifyListeners (
445
- prevResult : QueryObserverResult ,
459
+ prevResult : QueryObserverResult | undefined ,
446
460
result : QueryObserverResult
447
461
) : boolean {
448
462
const { notifyOnChangeProps, notifyOnChangePropsExclusions } = this . options
@@ -451,6 +465,10 @@ export class QueryObserver<
451
465
return false
452
466
}
453
467
468
+ if ( ! prevResult ) {
469
+ return true
470
+ }
471
+
454
472
if ( ! notifyOnChangeProps && ! notifyOnChangePropsExclusions ) {
455
473
return true
456
474
}
@@ -485,39 +503,60 @@ export class QueryObserver<
485
503
return false
486
504
}
487
505
488
- private updateResult ( willFetch ?: boolean ) : void {
489
- const result = this . getNewResult ( willFetch )
506
+ private updateResult ( action ?: Action < TData , TError > ) : void {
507
+ const prevResult = this . currentResult as
508
+ | QueryObserverResult < TData , TError >
509
+ | undefined
510
+
511
+ const result = this . getNewResult ( )
490
512
491
513
// Keep reference to the current state on which the current result is based on
492
514
this . currentResultState = this . currentQuery . state
493
515
494
516
// Only update if something has changed
495
- if ( ! shallowEqualObjects ( result , this . currentResult ) ) {
496
- this . currentResult = result
517
+ if ( shallowEqualObjects ( result , prevResult ) ) {
518
+ return
519
+ }
497
520
498
- if ( this . options . notifyOnChangeProps === 'tracked' ) {
499
- const addTrackedProps = ( prop : keyof QueryObserverResult ) => {
500
- if ( ! this . trackedProps . includes ( prop ) ) {
501
- this . trackedProps . push ( prop )
502
- }
521
+ this . currentResult = result
522
+
523
+ if ( this . options . notifyOnChangeProps === 'tracked' ) {
524
+ const addTrackedProps = ( prop : keyof QueryObserverResult ) => {
525
+ if ( ! this . trackedProps . includes ( prop ) ) {
526
+ this . trackedProps . push ( prop )
503
527
}
504
- this . trackedCurrentResult = { } as QueryObserverResult < TData , TError >
505
-
506
- Object . keys ( result ) . forEach ( key => {
507
- Object . defineProperty ( this . trackedCurrentResult , key , {
508
- configurable : false ,
509
- enumerable : true ,
510
- get ( ) {
511
- addTrackedProps ( key as keyof QueryObserverResult )
512
- return result [ key as keyof QueryObserverResult ]
513
- } ,
514
- } )
515
- } )
516
528
}
529
+ this . trackedCurrentResult = { } as QueryObserverResult < TData , TError >
530
+
531
+ Object . keys ( result ) . forEach ( key => {
532
+ Object . defineProperty ( this . trackedCurrentResult , key , {
533
+ configurable : false ,
534
+ enumerable : true ,
535
+ get ( ) {
536
+ addTrackedProps ( key as keyof QueryObserverResult )
537
+ return result [ key as keyof QueryObserverResult ]
538
+ } ,
539
+ } )
540
+ } )
541
+ }
542
+
543
+ // Determine which callbacks to trigger
544
+ const notifyOptions : NotifyOptions = { cache : true }
545
+
546
+ if ( action ?. type === 'success' ) {
547
+ notifyOptions . onSuccess = true
548
+ } else if ( action ?. type === 'error' ) {
549
+ notifyOptions . onError = true
517
550
}
551
+
552
+ if ( this . shouldNotifyListeners ( prevResult , result ) ) {
553
+ notifyOptions . listeners = true
554
+ }
555
+
556
+ this . notify ( notifyOptions )
518
557
}
519
558
520
- private updateQuery ( ) : void {
559
+ private updateQuery ( ) : boolean {
521
560
const prevQuery = this . currentQuery
522
561
523
562
const query = this . client
@@ -528,62 +567,27 @@ export class QueryObserver<
528
567
)
529
568
530
569
if ( query === prevQuery ) {
531
- return
570
+ return false
532
571
}
533
572
534
573
this . previousQueryResult = this . currentResult
535
574
this . currentQuery = query
536
575
this . initialDataUpdateCount = query . state . dataUpdateCount
537
576
this . initialErrorUpdateCount = query . state . errorUpdateCount
538
577
539
- const willFetch = prevQuery
540
- ? this . willFetchOptionally ( )
541
- : this . willFetchOnMount ( )
542
-
543
- this . updateResult ( willFetch )
544
-
545
- if ( ! this . hasListeners ( ) ) {
546
- return
578
+ if ( this . hasListeners ( ) ) {
579
+ prevQuery ?. removeObserver ( this )
580
+ this . currentQuery . addObserver ( this )
547
581
}
548
582
549
- prevQuery ?. removeObserver ( this )
550
- this . currentQuery . addObserver ( this )
551
-
552
- if (
553
- this . shouldNotifyListeners ( this . previousQueryResult , this . currentResult )
554
- ) {
555
- this . notify ( { listeners : true } )
556
- }
583
+ return true
557
584
}
558
585
559
586
onQueryUpdate ( action : Action < TData , TError > ) : void {
560
- // Store current result and get new result
561
- const prevResult = this . currentResult
562
- this . updateResult ( )
563
- const currentResult = this . currentResult
564
-
565
- // Update timers
566
- this . updateTimers ( )
567
-
568
- // Do not notify if the nothing has changed
569
- if ( prevResult === currentResult ) {
570
- return
571
- }
572
-
573
- // Determine which callbacks to trigger
574
- const notifyOptions : NotifyOptions = { }
575
-
576
- if ( action . type === 'success' ) {
577
- notifyOptions . onSuccess = true
578
- } else if ( action . type === 'error' ) {
579
- notifyOptions . onError = true
580
- }
581
-
582
- if ( this . shouldNotifyListeners ( prevResult , currentResult ) ) {
583
- notifyOptions . listeners = true
587
+ this . updateResult ( action )
588
+ if ( this . hasListeners ( ) ) {
589
+ this . updateTimers ( )
584
590
}
585
-
586
- this . notify ( notifyOptions )
587
591
}
588
592
589
593
private notify ( notifyOptions : NotifyOptions ) : void {
0 commit comments