Skip to content

Commit

Permalink
Set fetchStatus to idle when dehydrating (#4974)
Browse files Browse the repository at this point in the history
* πŸ› Set fetchStatus to idle when dehydrating

* βœ… Add a test case for ensuring fetchStatus is idle

* βœ… Update tests

* 🚨 Fix lint warnings

* βœ… Update fetchStatus when hydrating

* :okay_hand: Review updates

---------

Co-authored-by: Dominik Dorfmeister <[email protected]>
  • Loading branch information
prateek3255 and TkDodo authored Feb 18, 2023
1 parent f14590b commit 8e7a316
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
13 changes: 10 additions & 3 deletions packages/query-core/src/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,17 @@ export function hydrate(
queries.forEach((dehydratedQuery) => {
const query = queryCache.get(dehydratedQuery.queryHash)

// Reset fetch status to idle in the dehydrated state to avoid
// query being stuck in fetching state upon hydration
const dehydratedQueryState = {
...dehydratedQuery.state,
fetchStatus: 'idle' as const,
}

// Do not hydrate if an existing query exists with newer data
if (query) {
if (query.state.dataUpdatedAt < dehydratedQuery.state.dataUpdatedAt) {
query.setState(dehydratedQuery.state)
if (query.state.dataUpdatedAt < dehydratedQueryState.dataUpdatedAt) {
query.setState(dehydratedQueryState)
}
return
}
Expand All @@ -158,7 +165,7 @@ export function hydrate(
queryKey: dehydratedQuery.queryKey,
queryHash: dehydratedQuery.queryHash,
},
dehydratedQuery.state,
dehydratedQueryState,
)
})
}
40 changes: 40 additions & 0 deletions packages/query-core/src/tests/hydration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,44 @@ describe('dehydration and rehydration', () => {

queryClient.clear()
})

test('should set the fetchStatus to idle in all cases when dehydrating', async () => {
const queryCache = new QueryCache()
const queryClient = createQueryClient({ queryCache })

let isInitialFetch = true
let resolvePromise: (value: unknown) => void = () => undefined

const customFetchData = () => {
const promise = new Promise((resolve) => {
resolvePromise = resolve
})
// Resolve the promise in initial fetch
// because we are awaiting the query first time
if (isInitialFetch) {
resolvePromise('string')
}
isInitialFetch = false
return promise
}

await queryClient.prefetchQuery(['string'], () => customFetchData())

queryClient.refetchQueries(['string'])

const dehydrated = dehydrate(queryClient)
resolvePromise('string')
expect(
dehydrated.queries.find((q) => q.queryHash === '["string"]')?.state
.fetchStatus,
).toBe('fetching')
const stringified = JSON.stringify(dehydrated)

// ---
const parsed = JSON.parse(stringified)
const hydrationCache = new QueryCache()
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
hydrate(hydrationClient, parsed)
expect(hydrationCache.find(['string'])?.state.fetchStatus).toBe('idle')
})
})

0 comments on commit 8e7a316

Please sign in to comment.