Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silver-places-pick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/query-core': minor
---

feat(query-core): accept callback function for retryOnMount
5 changes: 3 additions & 2 deletions docs/framework/react/reference/useQuery.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ const {
- If set to a `number`, e.g. `3`, failed queries will retry until the failed query count meets that number.
- If set to a function, it will be called with `failureCount` (starting at `0` for the first retry) and `error` to determine if a retry should be attempted.
- defaults to `3` on the client and `0` on the server
- `retryOnMount: boolean`
- If set to `false`, the query will not be retried on mount if it contains an error. Defaults to `true`.
- `retryOnMount: boolean | (query: Query) => boolean`
- If set to `false`, the query will not be retried on mount if it contains an error and has no data. Defaults to `true`.
- If set to a function, the function will be executed with the query to compute the value.
- `retryDelay: number | (retryAttempt: number, error: TError) => number`
- This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.
- A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
Expand Down
5 changes: 3 additions & 2 deletions docs/framework/solid/reference/useQuery.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,9 @@ function App() {
- If `true`, failed queries will retry infinitely.
- If set to a `number`, e.g. `3`, failed queries will retry until the failed query count meets that number.
- defaults to `3` on the client and `0` on the server
- ##### `retryOnMount: boolean`
- If set to `false`, the query will not be retried on mount if it contains an error. Defaults to `true`.
- ##### `retryOnMount: boolean | (query: Query) => boolean`
- If set to `false`, the query will not be retried on mount if it contains an error and has no data. Defaults to `true`.
- If set to a function, the function will be executed with the query to compute the value.
- ##### `retryDelay: number | (retryAttempt: number, error: TError) => number`
- This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.
- A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ describe('QueryErrorResetBoundary', () => {
}),
retry: false,
throwOnError: true,
retryOnMount: true,
retryOnMount: () => true,
},
],
})
Expand Down Expand Up @@ -818,7 +818,7 @@ describe('QueryErrorResetBoundary', () => {
return 'data'
}),
retry: false,
retryOnMount: true,
retryOnMount: () => true,
},
],
})
Expand Down
10 changes: 5 additions & 5 deletions packages/preact-query/src/__tests__/useQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4919,7 +4919,7 @@ describe('useQuery', () => {
queryFn,
enabled,
retry: false,
retryOnMount: false,
retryOnMount: () => false,
refetchOnMount: false,
refetchOnWindowFocus: false,
})
Expand Down Expand Up @@ -4979,7 +4979,7 @@ describe('useQuery', () => {
return 'data'
},
retry: false,
retryOnMount: false,
retryOnMount: () => false,
refetchOnMount: false,
refetchOnWindowFocus: false,
})
Expand Down Expand Up @@ -5033,7 +5033,7 @@ describe('useQuery', () => {
queryFn: () =>
sleep(10).then(() => Promise.reject<unknown>(new Error('Error'))),
retry: false,
retryOnMount: false,
retryOnMount: () => false,
refetchOnMount: false,
refetchOnWindowFocus: false,
})
Expand Down Expand Up @@ -6012,7 +6012,7 @@ describe('useQuery', () => {
queryKey: key,
queryFn,
retry: false,
retryOnMount: false,
retryOnMount: () => false,
})

states.push(state)
Expand Down Expand Up @@ -6433,7 +6433,7 @@ describe('useQuery', () => {
? () => sleep(10).then(() => Promise.resolve('data'))
: skipToken,
retry: false,
retryOnMount: false,
retryOnMount: () => false,
refetchOnMount: false,
refetchOnWindowFocus: false,
})
Expand Down
5 changes: 3 additions & 2 deletions packages/query-core/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
ensureQueryFn,
noop,
replaceData,
resolveEnabled,
resolveQueryBoolean,
resolveStaleTime,
skipToken,
timeUntilStale,
Expand Down Expand Up @@ -271,7 +271,8 @@ export class Query<

isActive(): boolean {
return this.observers.some(
(observer) => resolveEnabled(observer.options.enabled, this) !== false,
(observer) =>
resolveQueryBoolean(observer.options.enabled, this) !== false,
)
}

Expand Down
29 changes: 16 additions & 13 deletions packages/query-core/src/queryObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
isValidTimeout,
noop,
replaceData,
resolveEnabled,
resolveQueryBoolean,
resolveStaleTime,
shallowEqualObjects,
timeUntilStale,
Expand Down Expand Up @@ -153,7 +153,7 @@ export class QueryObserver<
this.options.enabled !== undefined &&
typeof this.options.enabled !== 'boolean' &&
typeof this.options.enabled !== 'function' &&
typeof resolveEnabled(this.options.enabled, this.#currentQuery) !==
typeof resolveQueryBoolean(this.options.enabled, this.#currentQuery) !==
'boolean'
) {
throw new Error(
Expand Down Expand Up @@ -197,8 +197,8 @@ export class QueryObserver<
if (
mounted &&
(this.#currentQuery !== prevQuery ||
resolveEnabled(this.options.enabled, this.#currentQuery) !==
resolveEnabled(prevOptions.enabled, this.#currentQuery) ||
resolveQueryBoolean(this.options.enabled, this.#currentQuery) !==
resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) ||
resolveStaleTime(this.options.staleTime, this.#currentQuery) !==
resolveStaleTime(prevOptions.staleTime, this.#currentQuery))
) {
Expand All @@ -211,8 +211,8 @@ export class QueryObserver<
if (
mounted &&
(this.#currentQuery !== prevQuery ||
resolveEnabled(this.options.enabled, this.#currentQuery) !==
resolveEnabled(prevOptions.enabled, this.#currentQuery) ||
resolveQueryBoolean(this.options.enabled, this.#currentQuery) !==
resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) ||
nextRefetchInterval !== this.#currentRefetchInterval)
) {
this.#updateRefetchInterval(nextRefetchInterval)
Expand Down Expand Up @@ -394,7 +394,7 @@ export class QueryObserver<

if (
environmentManager.isServer() ||
resolveEnabled(this.options.enabled, this.#currentQuery) === false ||
resolveQueryBoolean(this.options.enabled, this.#currentQuery) === false ||
!isValidTimeout(this.#currentRefetchInterval) ||
this.#currentRefetchInterval === 0
) {
Expand Down Expand Up @@ -589,7 +589,7 @@ export class QueryObserver<
isStale: isStale(query, options),
refetch: this.refetch,
promise: this.#currentThenable,
isEnabled: resolveEnabled(options.enabled, query) !== false,
isEnabled: resolveQueryBoolean(options.enabled, query) !== false,
}

const nextResult = result as QueryObserverResult<TData, TError>
Expand Down Expand Up @@ -750,9 +750,12 @@ function shouldLoadOnMount(
options: QueryObserverOptions<any, any, any, any>,
): boolean {
return (
resolveEnabled(options.enabled, query) !== false &&
resolveQueryBoolean(options.enabled, query) !== false &&
query.state.data === undefined &&
!(query.state.status === 'error' && options.retryOnMount === false)
!(
query.state.status === 'error' &&
resolveQueryBoolean(options.retryOnMount, query) === false
)
)
}

Expand All @@ -775,7 +778,7 @@ function shouldFetchOn(
(typeof options)['refetchOnReconnect'],
) {
if (
resolveEnabled(options.enabled, query) !== false &&
resolveQueryBoolean(options.enabled, query) !== false &&
resolveStaleTime(options.staleTime, query) !== 'static'
) {
const value = typeof field === 'function' ? field(query) : field
Expand All @@ -793,7 +796,7 @@ function shouldFetchOptionally(
): boolean {
return (
(query !== prevQuery ||
resolveEnabled(prevOptions.enabled, query) === false) &&
resolveQueryBoolean(prevOptions.enabled, query) === false) &&
(!options.suspense || query.state.status !== 'error') &&
isStale(query, options)
)
Expand All @@ -804,7 +807,7 @@ function isStale(
options: QueryObserverOptions<any, any, any, any, any>,
): boolean {
return (
resolveEnabled(options.enabled, query) !== false &&
resolveQueryBoolean(options.enabled, query) !== false &&
query.isStaleByTime(resolveStaleTime(options.staleTime, query))
)
}
Expand Down
7 changes: 4 additions & 3 deletions packages/query-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export type StaleTimeFunction<
| StaleTime
| ((query: Query<TQueryFnData, TError, TData, TQueryKey>) => StaleTime)

export type Enabled<
export type QueryBooleanOption<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
Expand Down Expand Up @@ -326,7 +326,7 @@ export interface QueryObserverOptions<
* Accepts a boolean or function that returns a boolean.
* Defaults to `true`.
*/
enabled?: Enabled<TQueryFnData, TError, TQueryData, TQueryKey>
enabled?: QueryBooleanOption<TQueryFnData, TError, TQueryData, TQueryKey>
/**
* The time in milliseconds after data is considered stale.
* If set to `Infinity`, the data will never be considered stale.
Expand Down Expand Up @@ -391,9 +391,10 @@ export interface QueryObserverOptions<
) => boolean | 'always')
/**
* If set to `false`, the query will not be retried on mount if it contains an error.
* If set to a function, the function will be executed with the query to compute the value.
* Defaults to `true`.
*/
retryOnMount?: boolean
retryOnMount?: QueryBooleanOption<TQueryFnData, TError, TQueryData, TQueryKey>
/**
* If set, the component will only re-render if any of the listed properties change.
* When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change.
Expand Down
10 changes: 6 additions & 4 deletions packages/query-core/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { timeoutManager } from './timeoutManager'
import type {
DefaultError,
Enabled,
FetchStatus,
MutationKey,
MutationStatus,
QueryBooleanOption,
QueryFunction,
QueryKey,
QueryOptions,
Expand Down Expand Up @@ -126,16 +126,18 @@ export function resolveStaleTime<
return typeof staleTime === 'function' ? staleTime(query) : staleTime
}

export function resolveEnabled<
export function resolveQueryBoolean<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
>(
enabled: undefined | Enabled<TQueryFnData, TError, TData, TQueryKey>,
option:
| undefined
| QueryBooleanOption<TQueryFnData, TError, TData, TQueryKey>,
query: Query<TQueryFnData, TError, TData, TQueryKey>,
): boolean | undefined {
return typeof enabled === 'function' ? enabled(query) : enabled
return typeof option === 'function' ? option(query) : option
}

export function matchQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ describe('QueryErrorResetBoundary', () => {
}),
retry: false,
throwOnError: true,
retryOnMount: true,
retryOnMount: () => true,
},
],
})
Expand Down Expand Up @@ -894,7 +894,7 @@ describe('QueryErrorResetBoundary', () => {
return 'data'
}),
retry: false,
retryOnMount: true,
retryOnMount: () => true,
},
],
})
Expand Down
Loading
Loading