Skip to content

Commit

Permalink
refactor(core): unify hydration options (#5131)
Browse files Browse the repository at this point in the history
* refactor: unify hydration options

* docs: update hydration docs

* migration guide

* refactor: use shouldDehydrate... syntax

* Update docs/react/guides/migrating-to-v5.md

Co-authored-by: Fredrik Höglund <[email protected]>

* Apply suggestions from code review

* chore: fix tests

* chore: fix tests

* Update docs/react/reference/hydration.md

---------

Co-authored-by: Fredrik Höglund <[email protected]>
  • Loading branch information
TkDodo and Ephem authored Apr 1, 2023
1 parent eff7f03 commit 4fa1cdb
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 59 deletions.
11 changes: 10 additions & 1 deletion docs/react/guides/migrating-to-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,15 @@ However, refetching all pages might lead to UI inconsistencies. Also, this optio

The v5 includes a new `maxPages` option for infinite queries to limit the number of pages to store in the query data and to refetch. This new feature handles the use cases initially identified for the `refetchPage` page feature without the related issues.

### New hydration API

The options you can pass to dehydrate have been simplified. Queries and Mutations are always dehydrated (according to the default function implementation). To change this behaviour, you can implement `shouldDehydrateQuery` or `shouldDehydrateMutation`.

```diff
- dehydrateMutations?: boolean
- dehydrateQueries?: boolean
```

### Infinite queries now need a `defaultPageParam`

Previously, we've passed `undefined` to the `queryFn` as `pageParam`, and you could assign a default value to the `pageParam` parameter in the `queryFn` function signature. This had the drawback of storing `undefined` in the `queryCache`, which is not serializable.
Expand Down Expand Up @@ -410,7 +419,7 @@ We have a new, simplified way to perform optimistic updates by leveraging the re

Here, we are only changing how the UI looks when the mutation is running instead of writing data directly to the cache. This works best if we only have one place where we need to show the optimistic update. For more details, have a look at the [optimistic updates documentation](../guides/optimistic-updates.md).

### Eternal list: scalable infinite query with new maxPages option
### Limited, Infinite Queries with new maxPages option

Infinite queries are great when infinite scroll or pagination are needed.
However, the more pages you fetch, the more memory you consume, and this also slows down the query refetching process as all the pages are sequentially refetched.
Expand Down
27 changes: 12 additions & 15 deletions docs/react/reference/hydration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { dehydrate } from '@tanstack/react-query'

const dehydratedState = dehydrate(queryClient, {
shouldDehydrateQuery,
shouldDehydrateMutation,
})
```

Expand All @@ -22,24 +23,20 @@ const dehydratedState = dehydrate(queryClient, {
- The `queryClient` that should be dehydrated
- `options: DehydrateOptions`
- Optional
- `dehydrateMutations: boolean`
- Optional
- Whether or not to dehydrate mutations.
- `dehydrateQueries: boolean`
- Optional
- Whether or not to dehydrate queries.
- `shouldDehydrateMutation: (mutation: Mutation) => boolean`
- Optional
- This function is called for each mutation in the cache
- Return `true` to include this mutation in dehydration, or `false` otherwise
- The default version only includes paused mutations
- If you would like to extend the function while retaining the previous behavior, import and execute `defaultShouldDehydrateMutation` as part of the return statement
- `shouldDehydrateQuery: (query: Query) => boolean`
- Whether to dehydrate mutations.
- The function is called for each mutation in the cache
- Return `true` to include this mutation in dehydration, or `false` otherwise
- Defaults to only including paused mutations
- If you would like to extend the function while retaining the default behavior, import and execute `defaultShouldDehydrateMutation` as part of the return statement
- `shouldDehydrateQuery: boolean | (query: Query) => boolean`
- Optional
- This function is called for each query in the cache
- Return `true` to include this query in dehydration, or `false` otherwise
- The default version only includes successful queries, do `shouldDehydrateQuery: () => true` to include all queries
- If you would like to extend the function while retaining the previous behavior, import and execute `defaultShouldDehydrateQuery` as part of the return statement
- Whether to dehydrate queries.
- The function, it is called for each query in the cache
- Return `true` to include this query in dehydration, or `false` otherwise
- Defaults to only including successful queries
- If you would like to extend the function while retaining the default behavior, import and execute `defaultShouldDehydrateQuery` as part of the return statement

**Returns**

Expand Down
55 changes: 18 additions & 37 deletions packages/query-core/src/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import type { Mutation, MutationState } from './mutation'
// TYPES

export interface DehydrateOptions {
dehydrateMutations?: boolean
dehydrateQueries?: boolean
shouldDehydrateMutation?: ShouldDehydrateMutationFunction
shouldDehydrateQuery?: ShouldDehydrateQueryFunction
shouldDehydrateMutation?: (mutation: Mutation) => boolean
shouldDehydrateQuery?: (query: Query) => boolean
}

export interface HydrateOptions {
Expand All @@ -40,10 +38,6 @@ export interface DehydratedState {
queries: DehydratedQuery[]
}

export type ShouldDehydrateQueryFunction = (query: Query) => boolean

export type ShouldDehydrateMutationFunction = (mutation: Mutation) => boolean

// FUNCTIONS

function dehydrateMutation(mutation: Mutation): DehydratedMutation {
Expand Down Expand Up @@ -77,36 +71,23 @@ export function dehydrate(
client: QueryClient,
options: DehydrateOptions = {},
): DehydratedState {
const mutations: DehydratedMutation[] = []
const queries: DehydratedQuery[] = []

if (options.dehydrateMutations !== false) {
const shouldDehydrateMutation =
options.shouldDehydrateMutation || defaultShouldDehydrateMutation

client
.getMutationCache()
.getAll()
.forEach((mutation) => {
if (shouldDehydrateMutation(mutation)) {
mutations.push(dehydrateMutation(mutation))
}
})
}
const filterMutation =
options.shouldDehydrateMutation ?? defaultShouldDehydrateMutation

const mutations = client
.getMutationCache()
.getAll()
.flatMap((mutation) =>
filterMutation(mutation) ? [dehydrateMutation(mutation)] : [],
)

if (options.dehydrateQueries !== false) {
const shouldDehydrateQuery =
options.shouldDehydrateQuery || defaultShouldDehydrateQuery

client
.getQueryCache()
.getAll()
.forEach((query) => {
if (shouldDehydrateQuery(query)) {
queries.push(dehydrateQuery(query))
}
})
}
const filterQuery =
options.shouldDehydrateQuery ?? defaultShouldDehydrateQuery

const queries = client
.getQueryCache()
.getAll()
.flatMap((query) => (filterQuery(query) ? [dehydrateQuery(query)] : []))

return { mutations, queries }
}
Expand Down
4 changes: 1 addition & 3 deletions packages/query-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export { isCancelledError } from './retryer'
export {
dehydrate,
hydrate,
defaultShouldDehydrateMutation,
defaultShouldDehydrateQuery,
defaultShouldDehydrateMutation,
} from './hydration'

// Types
Expand All @@ -35,6 +35,4 @@ export type {
DehydrateOptions,
DehydratedState,
HydrateOptions,
ShouldDehydrateMutationFunction,
ShouldDehydrateQueryFunction,
} from './hydration'
10 changes: 7 additions & 3 deletions packages/query-core/src/tests/hydration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ describe('dehydration and rehydration', () => {
queryFn: () => fetchData('string'),
})

const dehydrated = dehydrate(queryClient, { dehydrateQueries: false })
const dehydrated = dehydrate(queryClient, {
shouldDehydrateQuery: () => false,
})

expect(dehydrated.queries.length).toBe(0)

Expand Down Expand Up @@ -244,7 +246,7 @@ describe('dehydration and rehydration', () => {
consoleMock.mockRestore()
})

test('should filter queries via shouldDehydrateQuery', async () => {
test('should filter queries via dehydrateQuery', async () => {
const queryCache = new QueryCache()
const queryClient = createQueryClient({ queryCache })
await queryClient.prefetchQuery({
Expand Down Expand Up @@ -446,7 +448,9 @@ describe('dehydration and rehydration', () => {
).catch(() => undefined)

await sleep(1)
const dehydrated = dehydrate(queryClient, { dehydrateMutations: false })
const dehydrated = dehydrate(queryClient, {
shouldDehydrateMutation: () => false,
})

expect(dehydrated.mutations.length).toBe(0)

Expand Down

0 comments on commit 4fa1cdb

Please sign in to comment.