Skip to content

Commit a8f0451

Browse files
committed
Merge branch 'main' into beta
# Conflicts: # docs/react/reference/useInfiniteQuery.md # packages/react-query-persist-client/package.json # packages/react-query-persist-client/src/PersistQueryClientProvider.tsx # packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx
2 parents 6582671 + 22b2860 commit a8f0451

File tree

3 files changed

+78
-14
lines changed

3 files changed

+78
-14
lines changed

docs/react/reference/useInfiniteQuery.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,5 @@ The returned properties for `useInfiniteQuery` are identical to the [`useQuery`
8080
- `isRefetching: boolean`
8181
- Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending` or fetching of next or previous page
8282
- Is the same as `isFetching && !isPending && !isFetchingNextPage && !isFetchingPreviousPage`
83+
84+
Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default refetch behaviour, resulting in outdated data. Make sure to call these functions only in response to user actions, or add conditions like `hasNextPage && !isFetching`.

packages/react-query-persist-client/src/PersistQueryClientProvider.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
'use client'
22
import * as React from 'react'
33

4-
import { persistQueryClient } from '@tanstack/query-persist-client-core'
4+
import {
5+
persistQueryClientRestore,
6+
persistQueryClientSubscribe,
7+
} from '@tanstack/query-persist-client-core'
58
import { IsRestoringProvider, QueryClientProvider } from '@tanstack/react-query'
69
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
710
import type { QueryClientProviderProps } from '@tanstack/react-query'
@@ -27,28 +30,23 @@ export const PersistQueryClientProvider = ({
2730
})
2831

2932
React.useEffect(() => {
33+
const options = {
34+
...refs.current.persistOptions,
35+
queryClient: client,
36+
}
3037
if (!didRestore.current) {
3138
didRestore.current = true
3239
setIsRestoring(true)
33-
const [unsubscribe, promise] = persistQueryClient({
34-
...refs.current.persistOptions,
35-
queryClient: client,
36-
})
37-
38-
promise.then(async () => {
40+
persistQueryClientRestore(options).then(async () => {
3941
try {
4042
await refs.current.onSuccess?.()
4143
} finally {
4244
setIsRestoring(false)
4345
}
4446
})
45-
46-
return () => {
47-
unsubscribe()
48-
}
4947
}
50-
return undefined
51-
}, [client])
48+
return isRestoring ? undefined : persistQueryClientSubscribe(options)
49+
}, [client, isRestoring])
5250

5351
return (
5452
<QueryClientProvider client={client} {...props}>

packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react'
2-
import { render, waitFor } from '@testing-library/react'
2+
import { fireEvent, render, waitFor } from '@testing-library/react'
33
import { vi } from 'vitest'
44

55
import { QueryClient, useQueries, useQuery } from '@tanstack/react-query'
@@ -128,6 +128,70 @@ describe('PersistQueryClientProvider', () => {
128128
})
129129
})
130130

131+
test('should subscribe correctly in StrictMode', async () => {
132+
const key = queryKey()
133+
134+
const queryClient = createQueryClient()
135+
await queryClient.prefetchQuery({
136+
queryKey: key,
137+
queryFn: () => Promise.resolve('hydrated'),
138+
})
139+
140+
const persister = createMockPersister()
141+
142+
await persistQueryClientSave({ queryClient, persister })
143+
144+
queryClient.clear()
145+
146+
function Page() {
147+
const state = useQuery({
148+
queryKey: key,
149+
queryFn: async () => {
150+
await sleep(10)
151+
return 'fetched'
152+
},
153+
})
154+
155+
return (
156+
<div>
157+
<h1>{state.data}</h1>
158+
<h2>fetchStatus: {state.fetchStatus}</h2>
159+
<button
160+
onClick={() => {
161+
queryClient.setQueryData(key, 'updated')
162+
}}
163+
>
164+
update
165+
</button>
166+
</div>
167+
)
168+
}
169+
170+
const rendered = render(
171+
<React.StrictMode>
172+
<PersistQueryClientProvider
173+
client={queryClient}
174+
persistOptions={{ persister }}
175+
>
176+
<Page />
177+
</PersistQueryClientProvider>
178+
,
179+
</React.StrictMode>,
180+
)
181+
182+
await waitFor(() => rendered.getByText('fetchStatus: idle'))
183+
await waitFor(() => rendered.getByText('hydrated'))
184+
await waitFor(() => rendered.getByText('fetched'))
185+
186+
fireEvent.click(rendered.getByRole('button', { name: /update/i }))
187+
188+
await waitFor(() => rendered.getByText('updated'))
189+
190+
const state = await persister.restoreClient()
191+
192+
expect(state?.clientState.queries[0]?.state.data).toBe('updated')
193+
})
194+
131195
test('should also put useQueries into idle state', async () => {
132196
const key = queryKey()
133197
const states: Array<UseQueryResult> = []

0 commit comments

Comments
 (0)