@@ -87,6 +87,7 @@ export class QueryObserver<
8787 this . executeFetch ( )
8888 }
8989
90+ this . updateResult ( )
9091 this . updateTimers ( )
9192 }
9293 }
@@ -155,7 +156,6 @@ export class QueryObserver<
155156 options ?: QueryObserverOptions < TQueryFnData , TError , TData , TQueryData >
156157 ) : void {
157158 const prevOptions = this . options
158- const prevQuery = this . currentQuery
159159
160160 this . options = this . client . defaultQueryObserverOptions ( options )
161161
@@ -171,39 +171,60 @@ export class QueryObserver<
171171 this . options . queryKey = prevOptions . queryKey
172172 }
173173
174- this . updateQuery ( )
174+ const didUpdateQuery = this . updateQuery ( )
175175
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
180179
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
186185 }
187186
188187 // Optionally fetch if the query became enabled
189188 if ( this . options . enabled !== false && prevOptions . enabled === false ) {
190- this . optionalFetch ( )
189+ optionalFetch = true
191190 }
192191
193192 // Update stale interval if needed
194193 if (
195194 this . options . enabled !== prevOptions . enabled ||
196195 this . options . staleTime !== prevOptions . staleTime
197196 ) {
198- this . updateStaleTimeout ( )
197+ updateStaleTimeout = true
199198 }
200199
201200 // Update refetch interval if needed
202201 if (
203202 this . options . enabled !== prevOptions . enabled ||
204203 this . options . refetchInterval !== prevOptions . refetchInterval
205204 ) {
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+ }
207228 }
208229 }
209230
@@ -302,12 +323,7 @@ export class QueryObserver<
302323
303324 this . staleTimeoutId = setTimeout ( ( ) => {
304325 if ( ! this . currentResult . isStale ) {
305- const prevResult = this . currentResult
306326 this . updateResult ( )
307- this . notify ( {
308- listeners : this . shouldNotifyListeners ( prevResult , this . currentResult ) ,
309- cache : true ,
310- } )
311327 }
312328 } , timeout )
313329 }
@@ -353,9 +369,7 @@ export class QueryObserver<
353369 this . refetchIntervalId = undefined
354370 }
355371
356- protected getNewResult (
357- willFetch ?: boolean
358- ) : QueryObserverResult < TData , TError > {
372+ protected getNewResult ( ) : QueryObserverResult < TData , TError > {
359373 const { state } = this . currentQuery
360374 let { isFetching, status } = state
361375 let isPreviousData = false
@@ -364,7 +378,7 @@ export class QueryObserver<
364378 let dataUpdatedAt = state . dataUpdatedAt
365379
366380 // Optimistically set status to loading if we will start fetching
367- if ( willFetch ) {
381+ if ( ! this . hasListeners ( ) && this . willFetchOnMount ( ) ) {
368382 isFetching = true
369383 if ( ! dataUpdatedAt ) {
370384 status = 'loading'
@@ -442,7 +456,7 @@ export class QueryObserver<
442456 }
443457
444458 private shouldNotifyListeners (
445- prevResult : QueryObserverResult ,
459+ prevResult : QueryObserverResult | undefined ,
446460 result : QueryObserverResult
447461 ) : boolean {
448462 const { notifyOnChangeProps, notifyOnChangePropsExclusions } = this . options
@@ -451,6 +465,10 @@ export class QueryObserver<
451465 return false
452466 }
453467
468+ if ( ! prevResult ) {
469+ return true
470+ }
471+
454472 if ( ! notifyOnChangeProps && ! notifyOnChangePropsExclusions ) {
455473 return true
456474 }
@@ -485,39 +503,60 @@ export class QueryObserver<
485503 return false
486504 }
487505
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 ( )
490512
491513 // Keep reference to the current state on which the current result is based on
492514 this . currentResultState = this . currentQuery . state
493515
494516 // Only update if something has changed
495- if ( ! shallowEqualObjects ( result , this . currentResult ) ) {
496- this . currentResult = result
517+ if ( shallowEqualObjects ( result , prevResult ) ) {
518+ return
519+ }
497520
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 )
503527 }
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- } )
516528 }
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
517550 }
551+
552+ if ( this . shouldNotifyListeners ( prevResult , result ) ) {
553+ notifyOptions . listeners = true
554+ }
555+
556+ this . notify ( notifyOptions )
518557 }
519558
520- private updateQuery ( ) : void {
559+ private updateQuery ( ) : boolean {
521560 const prevQuery = this . currentQuery
522561
523562 const query = this . client
@@ -528,62 +567,27 @@ export class QueryObserver<
528567 )
529568
530569 if ( query === prevQuery ) {
531- return
570+ return false
532571 }
533572
534573 this . previousQueryResult = this . currentResult
535574 this . currentQuery = query
536575 this . initialDataUpdateCount = query . state . dataUpdateCount
537576 this . initialErrorUpdateCount = query . state . errorUpdateCount
538577
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 )
547581 }
548582
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
557584 }
558585
559586 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 ( )
584590 }
585-
586- this . notify ( notifyOptions )
587591 }
588592
589593 private notify ( notifyOptions : NotifyOptions ) : void {
0 commit comments