99 Updater ,
1010 replaceEqualDeep ,
1111} from './utils'
12- import { QueryInstance , OnStateUpdateFunction } from './queryInstance'
1312import {
1413 ArrayQueryKey ,
1514 InfiniteQueryConfig ,
@@ -19,7 +18,8 @@ import {
1918 QueryFunction ,
2019 QueryStatus ,
2120} from './types'
22- import { QueryCache } from './queryCache'
21+ import type { QueryCache } from './queryCache'
22+ import { QueryObserver , UpdateListener } from './queryObserver'
2323
2424// TYPES
2525
@@ -39,7 +39,7 @@ export interface QueryState<TResult, TError> {
3939 isError : boolean
4040 isFetched : boolean
4141 isFetching : boolean
42- isFetchingMore ? : IsFetchingMoreValue
42+ isFetchingMore : IsFetchingMoreValue
4343 isIdle : boolean
4444 isLoading : boolean
4545 isStale : boolean
@@ -111,7 +111,7 @@ export class Query<TResult, TError> {
111111 queryKey : ArrayQueryKey
112112 queryHash : string
113113 config : QueryConfig < TResult , TError >
114- instances : QueryInstance < TResult , TError > [ ]
114+ observers : QueryObserver < TResult , TError > [ ]
115115 state : QueryState < TResult , TError >
116116 shouldContinueRetryOnFocus ?: boolean
117117 promise ?: Promise < TResult | undefined >
@@ -131,17 +131,14 @@ export class Query<TResult, TError> {
131131 this . queryKey = init . queryKey
132132 this . queryHash = init . queryHash
133133 this . notifyGlobalListeners = init . notifyGlobalListeners
134- this . instances = [ ]
134+ this . observers = [ ]
135135 this . state = getDefaultState ( init . config )
136136
137137 if ( init . config . infinite ) {
138138 const infiniteConfig = init . config as InfiniteQueryConfig < TResult , TError >
139139 const infiniteData = ( this . state . data as unknown ) as TResult [ ] | undefined
140140
141- if (
142- typeof infiniteData !== 'undefined' &&
143- typeof this . state . canFetchMore === 'undefined'
144- ) {
141+ if ( typeof infiniteData !== 'undefined' ) {
145142 this . fetchMoreVariable = infiniteConfig . getFetchMore (
146143 infiniteData [ infiniteData . length - 1 ] ,
147144 infiniteData
@@ -154,11 +151,28 @@ export class Query<TResult, TError> {
154151 this . pageVariables = [ [ ...this . queryKey ] ]
155152 }
156153 }
154+
155+ // If the query started with data, schedule
156+ // a stale timeout
157+ if ( ! isServer && this . state . data ) {
158+ this . scheduleStaleTimeout ( )
159+
160+ // Simulate a query healing process
161+ this . heal ( )
162+
163+ // Schedule for garbage collection in case
164+ // nothing subscribes to this query
165+ this . scheduleGarbageCollection ( )
166+ }
167+ }
168+
169+ updateConfig ( config : QueryConfig < TResult , TError > ) : void {
170+ this . config = config
157171 }
158172
159173 private dispatch ( action : Action < TResult , TError > ) : void {
160174 this . state = queryReducer ( this . state , action )
161- this . instances . forEach ( d => d . onStateUpdate ( this . state , action ) )
175+ this . observers . forEach ( d => d . onQueryUpdate ( this . state , action ) )
162176 this . notifyGlobalListeners ( this )
163177 }
164178
@@ -169,11 +183,7 @@ export class Query<TResult, TError> {
169183
170184 this . clearStaleTimeout ( )
171185
172- if ( this . state . isStale ) {
173- return
174- }
175-
176- if ( this . config . staleTime === Infinity ) {
186+ if ( this . state . isStale || this . config . staleTime === Infinity ) {
177187 return
178188 }
179189
@@ -185,10 +195,6 @@ export class Query<TResult, TError> {
185195 invalidate ( ) : void {
186196 this . clearStaleTimeout ( )
187197
188- if ( ! this . queryCache . queries [ this . queryHash ] ) {
189- return
190- }
191-
192198 if ( this . state . isStale ) {
193199 return
194200 }
@@ -197,12 +203,12 @@ export class Query<TResult, TError> {
197203 }
198204
199205 scheduleGarbageCollection ( ) : void {
200- this . clearCacheTimeout ( )
201-
202- if ( ! this . queryCache . queries [ this . queryHash ] ) {
206+ if ( isServer ) {
203207 return
204208 }
205209
210+ this . clearCacheTimeout ( )
211+
206212 if ( this . config . cacheTime === Infinity ) {
207213 return
208214 }
@@ -244,9 +250,9 @@ export class Query<TResult, TError> {
244250 delete this . promise
245251 }
246252
247- clearIntervals ( ) : void {
248- this . instances . forEach ( instance => {
249- instance . clearInterval ( )
253+ private clearTimersObservers ( ) : void {
254+ this . observers . forEach ( observer => {
255+ observer . clearRefetchInterval ( )
250256 } )
251257 }
252258
@@ -310,19 +316,57 @@ export class Query<TResult, TError> {
310316 this . clearStaleTimeout ( )
311317 this . clearCacheTimeout ( )
312318 this . clearRetryTimeout ( )
313- this . clearIntervals ( )
319+ this . clearTimersObservers ( )
314320 this . cancel ( )
315321 delete this . queryCache . queries [ this . queryHash ]
316322 this . notifyGlobalListeners ( this )
317323 }
318324
325+ isEnabled ( ) : boolean {
326+ return this . observers . some ( observer => observer . config . enabled )
327+ }
328+
329+ shouldRefetchOnWindowFocus ( ) : boolean {
330+ return (
331+ this . isEnabled ( ) &&
332+ this . state . isStale &&
333+ this . observers . some ( observer => observer . config . refetchOnWindowFocus )
334+ )
335+ }
336+
319337 subscribe (
320- onStateUpdate ?: OnStateUpdateFunction < TResult , TError >
321- ) : QueryInstance < TResult , TError > {
322- const instance = new QueryInstance ( this , onStateUpdate )
323- this . instances . push ( instance )
338+ listener ?: UpdateListener < TResult , TError >
339+ ) : QueryObserver < TResult , TError > {
340+ const observer = new QueryObserver < TResult , TError > ( {
341+ queryCache : this . queryCache ,
342+ queryKey : this . queryKey ,
343+ ...this . config ,
344+ } )
345+
346+ observer . subscribe ( listener )
347+
348+ return observer
349+ }
350+
351+ subscribeObserver ( observer : QueryObserver < TResult , TError > ) : void {
352+ this . observers . push ( observer )
324353 this . heal ( )
325- return instance
354+ }
355+
356+ unsubscribeObserver (
357+ observer : QueryObserver < TResult , TError > ,
358+ preventGC ?: boolean
359+ ) : void {
360+ this . observers = this . observers . filter ( x => x !== observer )
361+
362+ if ( ! this . observers . length ) {
363+ this . cancel ( )
364+
365+ if ( ! preventGC ) {
366+ // Schedule garbage collection
367+ this . scheduleGarbageCollection ( )
368+ }
369+ }
326370 }
327371
328372 // Set up the core fetcher function
@@ -332,7 +376,11 @@ export class Query<TResult, TError> {
332376 ) : Promise < TResult > {
333377 try {
334378 // Perform the query
335- const promiseOrValue = fn ( ...this . config . queryFnParamsFilter ! ( args ) )
379+ const filter = this . config . queryFnParamsFilter
380+ const params = filter ? filter ( args ) : args
381+
382+ // Perform the query
383+ const promiseOrValue = fn ( ...params )
336384
337385 this . cancelPromises = ( ) => ( promiseOrValue as any ) ?. cancel ?.( )
338386
@@ -584,6 +632,7 @@ function getDefaultState<TResult, TError>(
584632 error : null ,
585633 isFetched : false ,
586634 isFetching : initialStatus === QueryStatus . Loading ,
635+ isFetchingMore : false ,
587636 failureCount : 0 ,
588637 isStale,
589638 data : initialData ,
0 commit comments