diff --git a/packages/toolkit/src/query/react/buildHooks.ts b/packages/toolkit/src/query/react/buildHooks.ts index 3496e934ef..86ee665d82 100644 --- a/packages/toolkit/src/query/react/buildHooks.ts +++ b/packages/toolkit/src/query/react/buildHooks.ts @@ -1661,8 +1661,6 @@ export function buildHooks({ skipPollingIfUnfocused, }) - const lastRenderHadSubscription = useRef(false) - const initialPageParam = (rest as UseInfiniteQuerySubscriptionOptions) .initialPageParam const stableInitialPageParam = useShallowStableValue(initialPageParam) @@ -1686,11 +1684,7 @@ export function buildHooks({ } const subscriptionRemoved = - !currentRenderHasSubscription && lastRenderHadSubscription.current - - usePossiblyImmediateEffect(() => { - lastRenderHadSubscription.current = currentRenderHasSubscription - }) + !currentRenderHasSubscription && promiseRef.current !== undefined usePossiblyImmediateEffect((): void | undefined => { if (subscriptionRemoved) { diff --git a/packages/toolkit/src/query/tests/buildHooks.test.tsx b/packages/toolkit/src/query/tests/buildHooks.test.tsx index 81af7c40ca..0d2af5b3fc 100644 --- a/packages/toolkit/src/query/tests/buildHooks.test.tsx +++ b/packages/toolkit/src/query/tests/buildHooks.test.tsx @@ -902,6 +902,71 @@ describe('hooks tests', () => { status: 'uninitialized', }) }) + + test('hook should not be stuck loading post resetApiState after re-render', async () => { + const user = userEvent.setup() + + function QueryComponent() { + const { isLoading, data } = api.endpoints.getUser.useQuery(1) + + if (isLoading) { + return

Loading...

+ } + + return

{data?.name}

+ } + + function Wrapper() { + const [open, setOpen] = useState(true) + + const handleRerender = () => { + setOpen(false) + setTimeout(() => { + setOpen(true) + }, 1000) + } + + const handleReset = () => { + storeRef.store.dispatch(api.util.resetApiState()) + } + + return ( + <> + + {open ? ( +
+ + + +
+ ) : null} + + ) + } + + render(, { wrapper: storeRef.wrapper }) + + await user.click( + screen.getByRole('button', { name: /Rerender component/i }), + ) + await waitFor(() => { + expect(screen.getByText('Timmy')).toBeTruthy() + }) + + await user.click( + screen.getByRole('button', { name: /reset api state/i }), + ) + await waitFor(() => { + expect(screen.queryByText('Loading...')).toBeNull() + }) + await waitFor(() => { + expect(screen.getByText('Timmy')).toBeTruthy() + }) + }) }) test('useQuery refetch method returns a promise that resolves with the result', async () => { diff --git a/packages/toolkit/src/query/tests/createApi.test.ts b/packages/toolkit/src/query/tests/createApi.test.ts index 6b1e8a093f..9fc0b11ded 100644 --- a/packages/toolkit/src/query/tests/createApi.test.ts +++ b/packages/toolkit/src/query/tests/createApi.test.ts @@ -1181,7 +1181,7 @@ describe('timeout behavior', () => { http.get( 'https://example.com/success', async () => { - await delay(10) + await delay(50) return HttpResponse.json({ value: 'failed' }, { status: 500 }) }, { once: true },