Skip to content

Commit c89fce3

Browse files
fix(rtk-query): useQuery hook does not refetch after resetApiState (#4758)
* fix: useQuery hook does not refetch after resetApiState * Update packages/toolkit/src/query/tests/buildHooks.test.tsx * Try fixing flaky timeout test --------- Co-authored-by: Mark Erikson <[email protected]>
1 parent 45a95cb commit c89fce3

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

packages/toolkit/src/query/react/buildHooks.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,8 +1661,6 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
16611661
skipPollingIfUnfocused,
16621662
})
16631663

1664-
const lastRenderHadSubscription = useRef(false)
1665-
16661664
const initialPageParam = (rest as UseInfiniteQuerySubscriptionOptions<any>)
16671665
.initialPageParam
16681666
const stableInitialPageParam = useShallowStableValue(initialPageParam)
@@ -1686,11 +1684,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
16861684
}
16871685

16881686
const subscriptionRemoved =
1689-
!currentRenderHasSubscription && lastRenderHadSubscription.current
1690-
1691-
usePossiblyImmediateEffect(() => {
1692-
lastRenderHadSubscription.current = currentRenderHasSubscription
1693-
})
1687+
!currentRenderHasSubscription && promiseRef.current !== undefined
16941688

16951689
usePossiblyImmediateEffect((): void | undefined => {
16961690
if (subscriptionRemoved) {

packages/toolkit/src/query/tests/buildHooks.test.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,71 @@ describe('hooks tests', () => {
902902
status: 'uninitialized',
903903
})
904904
})
905+
906+
test('hook should not be stuck loading post resetApiState after re-render', async () => {
907+
const user = userEvent.setup()
908+
909+
function QueryComponent() {
910+
const { isLoading, data } = api.endpoints.getUser.useQuery(1)
911+
912+
if (isLoading) {
913+
return <p>Loading...</p>
914+
}
915+
916+
return <p>{data?.name}</p>
917+
}
918+
919+
function Wrapper() {
920+
const [open, setOpen] = useState(true)
921+
922+
const handleRerender = () => {
923+
setOpen(false)
924+
setTimeout(() => {
925+
setOpen(true)
926+
}, 1000)
927+
}
928+
929+
const handleReset = () => {
930+
storeRef.store.dispatch(api.util.resetApiState())
931+
}
932+
933+
return (
934+
<>
935+
<button onClick={handleRerender} aria-label="Rerender component">
936+
Rerender
937+
</button>
938+
{open ? (
939+
<div>
940+
<button onClick={handleReset} aria-label="Reset API state">
941+
Reset
942+
</button>
943+
944+
<QueryComponent />
945+
</div>
946+
) : null}
947+
</>
948+
)
949+
}
950+
951+
render(<Wrapper />, { wrapper: storeRef.wrapper })
952+
953+
await user.click(
954+
screen.getByRole('button', { name: /Rerender component/i }),
955+
)
956+
await waitFor(() => {
957+
expect(screen.getByText('Timmy')).toBeTruthy()
958+
})
959+
960+
await user.click(
961+
screen.getByRole('button', { name: /reset api state/i }),
962+
)
963+
await waitFor(() => {
964+
expect(screen.queryByText('Loading...')).toBeNull()
965+
})
966+
await waitFor(() => {
967+
expect(screen.getByText('Timmy')).toBeTruthy()
968+
})
969+
})
905970
})
906971

907972
test('useQuery refetch method returns a promise that resolves with the result', async () => {

packages/toolkit/src/query/tests/createApi.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1181,7 +1181,7 @@ describe('timeout behavior', () => {
11811181
http.get(
11821182
'https://example.com/success',
11831183
async () => {
1184-
await delay(10)
1184+
await delay(50)
11851185
return HttpResponse.json({ value: 'failed' }, { status: 500 })
11861186
},
11871187
{ once: true },

0 commit comments

Comments
 (0)