@@ -39,6 +39,7 @@ import type { MockInstance } from 'vitest'
39
39
// the refetching behavior of components.
40
40
let amount = 0
41
41
let nextItemId = 0
42
+ let refetchCount = 0
42
43
43
44
interface Item {
44
45
id : number
@@ -87,6 +88,17 @@ const api = createApi({
87
88
} ,
88
89
} ) ,
89
90
} ) ,
91
+ getUserWithRefetchError : build . query < { name : string } , number > ( {
92
+ queryFn : async ( id ) => {
93
+ refetchCount += 1
94
+
95
+ if ( refetchCount > 1 ) {
96
+ return { error : true } as any
97
+ }
98
+
99
+ return { data : { name : 'Timmy' } }
100
+ } ,
101
+ } ) ,
90
102
getIncrementedAmount : build . query < { amount : number } , void > ( {
91
103
query : ( ) => ( {
92
104
url : '' ,
@@ -431,6 +443,85 @@ describe('hooks tests', () => {
431
443
] )
432
444
} )
433
445
446
+ test ( 'isSuccess stays consistent if there is an error while refetching' , async ( ) => {
447
+ type LoadingState = {
448
+ id : number
449
+ isFetching : boolean
450
+ isSuccess : boolean
451
+ isError : boolean
452
+ }
453
+ const loadingHistory : LoadingState [ ] = [ ]
454
+
455
+ function Component ( { id = 1 } ) {
456
+ const queryRes = api . endpoints . getUserWithRefetchError . useQuery ( id )
457
+ const { refetch, data, status } = queryRes
458
+
459
+ useEffect ( ( ) => {
460
+ const { isFetching, isSuccess, isError } = queryRes
461
+ loadingHistory . push ( { id, isFetching, isSuccess, isError } )
462
+ } , [ id , queryRes ] )
463
+
464
+ return (
465
+ < div >
466
+ < button
467
+ onClick = { ( ) => {
468
+ console . log ( 'Refetching' )
469
+ refetch ( )
470
+ } }
471
+ >
472
+ refetch
473
+ </ button >
474
+ < div data-testid = "name" > { data ?. name } </ div >
475
+ < div data-testid = "status" > { status } </ div >
476
+ </ div >
477
+ )
478
+ }
479
+
480
+ render ( < Component /> , { wrapper : storeRef . wrapper } )
481
+
482
+ await waitFor ( ( ) =>
483
+ expect ( screen . getByTestId ( 'name' ) . textContent ) . toBe ( 'Timmy' ) ,
484
+ )
485
+
486
+ fireEvent . click ( screen . getByText ( 'refetch' ) )
487
+
488
+ await waitFor ( ( ) =>
489
+ expect ( screen . getByTestId ( 'status' ) . textContent ) . toBe ( 'pending' ) ,
490
+ )
491
+
492
+ await waitFor ( ( ) =>
493
+ expect ( screen . getByTestId ( 'status' ) . textContent ) . toBe ( 'rejected' ) ,
494
+ )
495
+
496
+ fireEvent . click ( screen . getByText ( 'refetch' ) )
497
+
498
+ await waitFor ( ( ) =>
499
+ expect ( screen . getByTestId ( 'status' ) . textContent ) . toBe ( 'pending' ) ,
500
+ )
501
+
502
+ await waitFor ( ( ) =>
503
+ expect ( screen . getByTestId ( 'status' ) . textContent ) . toBe ( 'rejected' ) ,
504
+ )
505
+
506
+ expect ( loadingHistory ) . toEqual ( [
507
+ // Initial renders
508
+ { id : 1 , isFetching : true , isSuccess : false , isError : false } ,
509
+ { id : 1 , isFetching : true , isSuccess : false , isError : false } ,
510
+ // Data is returned
511
+ { id : 1 , isFetching : false , isSuccess : true , isError : false } ,
512
+ // Started first refetch
513
+ { id : 1 , isFetching : true , isSuccess : true , isError : false } ,
514
+ // First refetch errored
515
+ { id : 1 , isFetching : false , isSuccess : false , isError : true } ,
516
+ // Started second refetch
517
+ // IMPORTANT We expect `isSuccess` to still be false,
518
+ // despite having started the refetch again.
519
+ { id : 1 , isFetching : true , isSuccess : false , isError : false } ,
520
+ // Second refetch errored
521
+ { id : 1 , isFetching : false , isSuccess : false , isError : true } ,
522
+ ] )
523
+ } )
524
+
434
525
test ( 'useQuery hook respects refetchOnMountOrArgChange: true' , async ( ) => {
435
526
let data , isLoading , isFetching
436
527
function User ( ) {
0 commit comments