Skip to content

Commit

Permalink
feat(react-query-persist-client): await onuccess (#5473)
Browse files Browse the repository at this point in the history
* fix: have `onSuccess` return a promise too so that we can await it

that way, invalidation or mutations that run in onSuccess will still keep isRestoring to be false, which avoids race conditions

* test: test for awaiting onSuccess

* docs: onSuccess
  • Loading branch information
TkDodo authored May 26, 2023
1 parent 7d6e6ec commit a6186e5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 5 deletions.
3 changes: 2 additions & 1 deletion docs/react/plugins/persistQueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,11 @@ ReactDOM.createRoot(rootElement).render(

- `persistOptions: PersistQueryClientOptions`
- all [options](#options) you can pass to [persistQueryClient](#persistqueryclient) minus the QueryClient itself
- `onSuccess?: () => void`
- `onSuccess?: () => Promise<unknown> | unknown`
- optional
- will be called when the initial restore is finished
- can be used to [resumePausedMutations](../reference/QueryClient#queryclientresumepausedmutations)
- if a Promise is returned, it will be awaited; restoring is seen as ongoing until then

### useIsRestoring

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { QueryClientProvider, IsRestoringProvider } from '@tanstack/react-query'

export type PersistQueryClientProviderProps = QueryClientProviderProps & {
persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
onSuccess?: () => void
onSuccess?: () => Promise<unknown> | unknown
}

export const PersistQueryClientProvider = ({
Expand All @@ -33,10 +33,13 @@ export const PersistQueryClientProvider = ({
queryClient: client,
})

promise.then(() => {
promise.then(async () => {
if (!isStale) {
refs.current.onSuccess?.()
setIsRestoring(false)
try {
await refs.current.onSuccess?.()
} finally {
setIsRestoring(false)
}
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,66 @@ describe('PersistQueryClientProvider', () => {
await waitFor(() => rendered.getByText('fetched'))
})

test('should await onSuccess after successful restoring', async () => {
const key = queryKey()

const queryClient = createQueryClient()
await queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
})

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })

queryClient.clear()

const states: Array<string> = []

function Page() {
const { data, fetchStatus } = useQuery({
queryKey: key,
queryFn: async () => {
states.push('fetching')
await sleep(10)
states.push('fetched')
return 'fetched'
},
})

return (
<div>
<h1>{data}</h1>
<h2>fetchStatus: {fetchStatus}</h2>
</div>
)
}

const rendered = render(
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
onSuccess={async () => {
states.push('onSuccess')
await sleep(20)
states.push('onSuccess done')
}}
>
<Page />
</PersistQueryClientProvider>,
)

await waitFor(() => rendered.getByText('hydrated'))
await waitFor(() => rendered.getByText('fetched'))
expect(states).toEqual([
'onSuccess',
'onSuccess done',
'fetching',
'fetched',
])
})

test('should remove cache after non-successful restoring', async () => {
const key = queryKey()
const consoleMock = vi.spyOn(console, 'error')
Expand Down

0 comments on commit a6186e5

Please sign in to comment.