File tree Expand file tree Collapse file tree 4 files changed +57
-4
lines changed Expand file tree Collapse file tree 4 files changed +57
-4
lines changed Original file line number Diff line number Diff line change @@ -1192,4 +1192,48 @@ describe('query', () => {
11921192 expect ( initialDataFn ) . toHaveBeenCalledTimes ( 1 )
11931193 expect ( query . state . data ) . toBe ( 'initial data' )
11941194 } )
1195+
1196+ test ( 'should not override fetching state when revert happens after new observer subscribes' , async ( ) => {
1197+ const key = queryKey ( )
1198+
1199+ // @ts -expect-error This field has been added for troubleshooting purposes. Disable ts error for testing.
1200+ const queryFn = vi . fn ( async ( { signal } ) => {
1201+ await sleep ( 50 )
1202+ return 'data'
1203+ } )
1204+
1205+ const query = new Query ( {
1206+ client : queryClient ,
1207+ queryKey : key ,
1208+ queryHash : hashQueryKeyByOptions ( key ) ,
1209+ options : { queryFn } ,
1210+ } )
1211+
1212+ const observer1 = new QueryObserver ( queryClient , {
1213+ queryKey : key ,
1214+ queryFn,
1215+ } )
1216+
1217+ query . addObserver ( observer1 )
1218+ const promise1 = query . fetch ( )
1219+
1220+ await vi . advanceTimersByTimeAsync ( 10 )
1221+
1222+ query . removeObserver ( observer1 )
1223+
1224+ const observer2 = new QueryObserver ( queryClient , {
1225+ queryKey : key ,
1226+ queryFn,
1227+ } )
1228+
1229+ query . addObserver ( observer2 )
1230+
1231+ query . fetch ( )
1232+
1233+ await promise1 . catch ( ( ) => { } )
1234+
1235+ await Promise . resolve ( )
1236+
1237+ expect ( query . state . fetchStatus ) . toBe ( 'fetching' )
1238+ } )
11951239} )
Original file line number Diff line number Diff line change @@ -349,7 +349,7 @@ export class Query<
349349 // we'll let the query continue so the result can be cached
350350 if ( this . #retryer) {
351351 if ( this . #abortSignalConsumed) {
352- this . #retryer. cancel ( { revert : true } )
352+ this . #retryer. cancel ( { revert : true , isObserverRemoval : true } )
353353 } else {
354354 this . #retryer. cancelRetry ( )
355355 }
@@ -553,16 +553,22 @@ export class Query<
553553 // so we hatch onto that promise
554554 return this . #retryer. promise
555555 } else if ( error . revert ) {
556+ if ( error . isObserverRemoval && this . observers . length > 0 ) {
557+ if ( this . state . data === undefined ) {
558+ throw error
559+ }
560+ return this . state . data
561+ }
562+
556563 this . setState ( {
557564 ...this . #revertState,
558565 fetchStatus : 'idle' as const ,
559566 } )
560- // transform error into reverted state data
561- // if the initial fetch was cancelled, we have no data, so we have
562- // to get reject with a CancelledError
567+
563568 if ( this . state . data === undefined ) {
564569 throw error
565570 }
571+
566572 return this . state . data
567573 }
568574 }
Original file line number Diff line number Diff line change @@ -58,10 +58,12 @@ export function canFetch(networkMode: NetworkMode | undefined): boolean {
5858export class CancelledError extends Error {
5959 revert ?: boolean
6060 silent ?: boolean
61+ isObserverRemoval ?: boolean
6162 constructor ( options ?: CancelOptions ) {
6263 super ( 'CancelledError' )
6364 this . revert = options ?. revert
6465 this . silent = options ?. silent
66+ this . isObserverRemoval = options ?. isObserverRemoval
6567 }
6668}
6769
Original file line number Diff line number Diff line change @@ -1329,6 +1329,7 @@ export interface DefaultOptions<TError = DefaultError> {
13291329export interface CancelOptions {
13301330 revert ?: boolean
13311331 silent ?: boolean
1332+ isObserverRemoval ?: boolean
13321333}
13331334
13341335export interface SetDataOptions {
You can’t perform that action at this time.
0 commit comments