11import {
22 isServer ,
33 functionalUpdate ,
4- cancelledError ,
54 isDocumentVisible ,
65 noop ,
76 Console ,
@@ -104,6 +103,8 @@ export type Action<TResult, TError> =
104103 | SetStateAction < TResult , TError >
105104 | SuccessAction < TResult >
106105
106+ class CancelledError extends Error { }
107+
107108// CLASS
108109
109110export class Query < TResult , TError > {
@@ -122,7 +123,7 @@ export class Query<TResult, TError> {
122123 private retryTimeout ?: number
123124 private staleTimeout ?: number
124125 private cancelPromises ?: ( ) => void
125- private cancelled ?: typeof cancelledError | null
126+ private cancelled ?: boolean
126127 private notifyGlobalListeners : ( query : Query < TResult , TError > ) => void
127128
128129 constructor ( init : QueryInitConfig < TResult , TError > ) {
@@ -157,12 +158,13 @@ export class Query<TResult, TError> {
157158 }
158159
159160 private dispatch ( action : Action < TResult , TError > ) : void {
160- const newState = queryReducer ( this . state , action )
161+ const prevState = this . state
162+ const newState = queryReducer ( prevState , action )
161163
162164 // Only update state if something has changed
163- if ( ! shallowEqual ( this . state , newState ) ) {
165+ if ( ! shallowEqual ( prevState , newState ) ) {
164166 this . state = newState
165- this . instances . forEach ( d => d . onStateUpdate ( newState , action ) )
167+ this . instances . forEach ( d => d . onStateUpdate ( newState , prevState , action ) )
166168 this . notifyGlobalListeners ( this )
167169 }
168170 }
@@ -236,11 +238,11 @@ export class Query<TResult, TError> {
236238 this . clearCacheTimeout ( )
237239
238240 // Mark the query as not cancelled
239- this . cancelled = null
241+ this . cancelled = false
240242 }
241243
242244 cancel ( ) : void {
243- this . cancelled = cancelledError
245+ this . cancelled = true
244246
245247 if ( this . cancelPromises ) {
246248 this . cancelPromises ( )
@@ -322,21 +324,30 @@ export class Query<TResult, TError> {
322324 args : ArrayQueryKey
323325 ) : Promise < TResult > {
324326 try {
327+ const filter = this . config . queryFnParamsFilter
328+ const params = filter ? filter ( args ) : args
329+
325330 // Perform the query
326- const promiseOrValue = fn ( ...this . config . queryFnParamsFilter ! ( args ) )
331+ const promiseOrValue = fn ( ...params )
327332
328333 this . cancelPromises = ( ) => ( promiseOrValue as any ) ?. cancel ?.( )
329334
330335 const data = await promiseOrValue
331336 delete this . shouldContinueRetryOnFocus
332337
333338 delete this . cancelPromises
334- if ( this . cancelled ) throw this . cancelled
339+
340+ if ( this . cancelled ) {
341+ throw new CancelledError ( )
342+ }
335343
336344 return data
337345 } catch ( error ) {
338346 delete this . cancelPromises
339- if ( this . cancelled ) throw this . cancelled
347+
348+ if ( this . cancelled ) {
349+ throw new CancelledError ( )
350+ }
340351
341352 // Do we need to retry the request?
342353 if (
@@ -368,14 +379,23 @@ export class Query<TResult, TError> {
368379 return await new Promise ( ( resolve , reject ) => {
369380 // Keep track of the retry timeout
370381 this . retryTimeout = setTimeout ( async ( ) => {
371- if ( this . cancelled ) return reject ( this . cancelled )
382+ if ( this . cancelled ) {
383+ return reject ( new CancelledError ( ) )
384+ }
372385
373386 try {
374387 const data = await this . tryFetchData ( fn , args )
375- if ( this . cancelled ) return reject ( this . cancelled )
388+
389+ if ( this . cancelled ) {
390+ return reject ( new CancelledError ( ) )
391+ }
392+
376393 resolve ( data )
377394 } catch ( error ) {
378- if ( this . cancelled ) return reject ( this . cancelled )
395+ if ( this . cancelled ) {
396+ return reject ( new CancelledError ( ) )
397+ }
398+
379399 reject ( error )
380400 }
381401 } , delay )
@@ -499,7 +519,7 @@ export class Query<TResult, TError> {
499519
500520 this . promise = ( async ( ) => {
501521 // If there are any retries pending for this query, kill them
502- this . cancelled = null
522+ this . cancelled = false
503523
504524 try {
505525 // Set up the query refreshing state
@@ -514,15 +534,17 @@ export class Query<TResult, TError> {
514534
515535 return data
516536 } catch ( error ) {
537+ const cancelled = error instanceof CancelledError
538+
517539 this . dispatch ( {
518540 type : ActionType . Error ,
519- cancelled : error === this . cancelled ,
541+ cancelled,
520542 error,
521543 } )
522544
523545 delete this . promise
524546
525- if ( error !== this . cancelled ) {
547+ if ( ! cancelled ) {
526548 throw error
527549 }
528550
@@ -556,11 +578,31 @@ function getDefaultState<TResult, TError>(
556578
557579 const hasInitialData = typeof initialData !== 'undefined'
558580
559- const isStale =
560- ! config . enabled ||
561- ( typeof config . initialStale === 'function'
562- ? config . initialStale ( )
563- : config . initialStale ?? ! hasInitialData )
581+ // A query is stale by default
582+ let isStale = true
583+
584+ if ( hasInitialData ) {
585+ // When initial data is provided, the query is not stale by default
586+ isStale = false
587+
588+ // Mark the query as stale if initialStale is set to `true`
589+ if ( config . initialStale === true ) {
590+ isStale = true
591+ }
592+
593+ // Mark the query as stale if initialStale is set to a function which returns `true`
594+ if (
595+ typeof config . initialStale === 'function' &&
596+ config . initialStale ( ) === true
597+ ) {
598+ isStale = true
599+ }
600+ }
601+
602+ // Always mark the query as stale when it is not enabled
603+ if ( ! config . enabled ) {
604+ isStale = true
605+ }
564606
565607 const initialStatus = hasInitialData
566608 ? QueryStatus . Success
0 commit comments