@@ -474,33 +474,6 @@ export type MutationTrigger<D extends MutationDefinition<any, any, any, any>> =
474
474
const defaultQueryStateSelector : QueryStateSelector < any , any > = ( x ) => x
475
475
const defaultMutationStateSelector : MutationStateSelector < any , any > = ( x ) => x
476
476
477
- const queryStatePreSelector = (
478
- currentState : QueryResultSelectorResult < any > ,
479
- lastResult : UseQueryStateDefaultResult < any >
480
- ) : UseQueryStateDefaultResult < any > => {
481
- // data is the last known good request result we have tracked - or if none has been tracked yet the last good result for the current args
482
- let data = currentState . isSuccess ? currentState . data : lastResult ?. data
483
- if ( data === undefined ) data = currentState . data
484
-
485
- const hasData = data !== undefined
486
-
487
- // isFetching = true any time a request is in flight
488
- const isFetching = currentState . isLoading
489
- // isLoading = true only when loading while no data is present yet (initial load with no data in the cache)
490
- const isLoading = ! hasData && isFetching
491
- // isSuccess = true when data is present
492
- const isSuccess = currentState . isSuccess || ( isFetching && hasData )
493
-
494
- return {
495
- ...currentState ,
496
- data,
497
- currentData : currentState . data ,
498
- isFetching,
499
- isLoading,
500
- isSuccess,
501
- } as UseQueryStateDefaultResult < any >
502
- }
503
-
504
477
/**
505
478
* Wrapper around `defaultQueryStateSelector` to be used in `useQuery`.
506
479
* We want the initial render to already come back with
@@ -560,6 +533,55 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
560
533
561
534
return { buildQueryHooks, buildMutationHook, usePrefetch }
562
535
536
+ function queryStatePreSelector (
537
+ currentState : QueryResultSelectorResult < any > ,
538
+ lastResult : UseQueryStateDefaultResult < any > | undefined ,
539
+ queryArgs : any
540
+ ) : UseQueryStateDefaultResult < any > {
541
+ // if we had a last result and the current result is uninitialized,
542
+ // we might have called `api.util.resetApiState`
543
+ // in this case, reset the hook
544
+ if ( lastResult ?. endpointName && currentState . isUninitialized ) {
545
+ const { endpointName } = lastResult
546
+ const endpointDefinition = context . endpointDefinitions [ endpointName ]
547
+ if (
548
+ serializeQueryArgs ( {
549
+ queryArgs : lastResult . originalArgs ,
550
+ endpointDefinition,
551
+ endpointName,
552
+ } ) ===
553
+ serializeQueryArgs ( {
554
+ queryArgs,
555
+ endpointDefinition,
556
+ endpointName,
557
+ } )
558
+ )
559
+ lastResult = undefined
560
+ }
561
+
562
+ // data is the last known good request result we have tracked - or if none has been tracked yet the last good result for the current args
563
+ let data = currentState . isSuccess ? currentState . data : lastResult ?. data
564
+ if ( data === undefined ) data = currentState . data
565
+
566
+ const hasData = data !== undefined
567
+
568
+ // isFetching = true any time a request is in flight
569
+ const isFetching = currentState . isLoading
570
+ // isLoading = true only when loading while no data is present yet (initial load with no data in the cache)
571
+ const isLoading = ! hasData && isFetching
572
+ // isSuccess = true when data is present
573
+ const isSuccess = currentState . isSuccess || ( isFetching && hasData )
574
+
575
+ return {
576
+ ...currentState ,
577
+ data,
578
+ currentData : currentState . data ,
579
+ isFetching,
580
+ isLoading,
581
+ isSuccess,
582
+ } as UseQueryStateDefaultResult < any >
583
+ }
584
+
563
585
function usePrefetch < EndpointName extends QueryKeys < Definitions > > (
564
586
endpointName : EndpointName ,
565
587
defaultOptions ?: PrefetchOptions
@@ -609,8 +631,27 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
609
631
610
632
const promiseRef = useRef < QueryActionCreatorResult < any > > ( )
611
633
634
+ let { queryCacheKey, requestId } = promiseRef . current || { }
635
+ const subscriptionRemoved = useSelector (
636
+ ( state : RootState < Definitions , string , string > ) =>
637
+ ! ! queryCacheKey &&
638
+ ! ! requestId &&
639
+ ! state [ api . reducerPath ] . subscriptions [ queryCacheKey ] ?. [ requestId ]
640
+ )
641
+
642
+ usePossiblyImmediateEffect ( ( ) : void | undefined => {
643
+ promiseRef . current = undefined
644
+ } , [ subscriptionRemoved ] )
645
+
612
646
usePossiblyImmediateEffect ( ( ) : void | undefined => {
613
647
const lastPromise = promiseRef . current
648
+ if (
649
+ typeof process !== 'undefined' &&
650
+ process . env . NODE_ENV === 'removeMeOnCompilation'
651
+ ) {
652
+ // this is only present to enforce the rule of hooks to keep `isSubscribed` in the dependency array
653
+ console . log ( subscriptionRemoved )
654
+ }
614
655
615
656
if ( stableArg === skipToken ) {
616
657
lastPromise ?. unsubscribe ( )
@@ -638,6 +679,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
638
679
refetchOnMountOrArgChange ,
639
680
stableArg ,
640
681
stableSubscriptionOptions ,
682
+ subscriptionRemoved ,
641
683
] )
642
684
643
685
useEffect ( ( ) => {
@@ -752,7 +794,11 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
752
794
const selectDefaultResult = useMemo (
753
795
( ) =>
754
796
createSelector (
755
- [ select ( stableArg ) , ( _ : any , lastResult : any ) => lastResult ] ,
797
+ [
798
+ select ( stableArg ) ,
799
+ ( _ : any , lastResult : any ) => lastResult ,
800
+ ( ) => stableArg ,
801
+ ] ,
756
802
queryStatePreSelector
757
803
) ,
758
804
[ select , stableArg ]
0 commit comments