From 6d6be328194b981c13e673268a38de659dfa0309 Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 12:14:30 -0800 Subject: [PATCH 1/6] add isPending alias to isLoading --- packages/query-core/src/mutationObserver.ts | 1 + packages/query-core/src/queryObserver.ts | 2 ++ packages/query-core/src/types.ts | 25 +++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/packages/query-core/src/mutationObserver.ts b/packages/query-core/src/mutationObserver.ts index 5b0c0eba4e..dc5c4c125d 100644 --- a/packages/query-core/src/mutationObserver.ts +++ b/packages/query-core/src/mutationObserver.ts @@ -149,6 +149,7 @@ export class MutationObserver< > = { ...state, isLoading: state.status === 'loading', + isPending: state.status === 'loading', isSuccess: state.status === 'success', isError: state.status === 'error', isIdle: state.status === 'idle', diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts index e4095a13f5..fb7803cf6f 100644 --- a/packages/query-core/src/queryObserver.ts +++ b/packages/query-core/src/queryObserver.ts @@ -577,12 +577,14 @@ export class QueryObserver< const isFetching = fetchStatus === 'fetching' const isLoading = status === 'loading' + const isPending = status === 'loading' const isError = status === 'error' const result: QueryObserverBaseResult = { status, fetchStatus, isLoading, + isPending, isSuccess: status === 'success', isError, isInitialLoading: isLoading && isFetching, diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index cfeae31fb9..65606fa8fd 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -393,7 +393,9 @@ export interface QueryObserverBaseResult { isFetched: boolean isFetchedAfterMount: boolean isFetching: boolean + /** @deprecated Removed in v5. Use isPending instead */ isLoading: boolean + isPending: boolean isLoadingError: boolean isInitialLoading: boolean isPaused: boolean @@ -416,7 +418,9 @@ export interface QueryObserverLoadingResult data: undefined error: null isError: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: true + isPending: true isLoadingError: false isRefetchError: false isSuccess: false @@ -430,7 +434,9 @@ export interface QueryObserverLoadingErrorResult< data: undefined error: TError isError: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: true isRefetchError: false isSuccess: false @@ -444,6 +450,7 @@ export interface QueryObserverRefetchErrorResult< data: TData error: TError isError: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false isLoadingError: false isRefetchError: true @@ -456,7 +463,9 @@ export interface QueryObserverSuccessResult data: TData error: null isError: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: false isRefetchError: false isSuccess: true @@ -495,7 +504,9 @@ export interface InfiniteQueryObserverLoadingResult< data: undefined error: null isError: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: true + isPending: true isLoadingError: false isRefetchError: false isSuccess: false @@ -509,7 +520,9 @@ export interface InfiniteQueryObserverLoadingErrorResult< data: undefined error: TError isError: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: true isRefetchError: false isSuccess: false @@ -523,7 +536,9 @@ export interface InfiniteQueryObserverRefetchErrorResult< data: InfiniteData error: TError isError: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: false isRefetchError: true isSuccess: false @@ -537,7 +552,9 @@ export interface InfiniteQueryObserverSuccessResult< data: InfiniteData error: null isError: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: false isRefetchError: false isSuccess: true @@ -645,7 +662,9 @@ export interface MutationObserverBaseResult< > extends MutationState { isError: boolean isIdle: boolean + /** @deprecated Removed in v5. Use isPending instead */ isLoading: boolean + isPending: boolean isSuccess: boolean mutate: MutateFunction reset: () => void @@ -661,6 +680,7 @@ export interface MutationObserverIdleResult< error: null isError: false isIdle: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false isSuccess: false status: 'idle' @@ -676,7 +696,9 @@ export interface MutationObserverLoadingResult< error: null isError: false isIdle: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: true + isPending: true isSuccess: false status: 'loading' } @@ -691,6 +713,7 @@ export interface MutationObserverErrorResult< error: TError isError: true isIdle: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false isSuccess: false status: 'error' @@ -706,7 +729,9 @@ export interface MutationObserverSuccessResult< error: null isError: false isIdle: false + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isSuccess: true status: 'success' } From 2d8f9f9735eecc1f13678bad04b785a82fec5689 Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 12:41:22 -0800 Subject: [PATCH 2/6] add useSuspenseQuery --- packages/query-core/src/types.ts | 1 + packages/react-query/src/types.ts | 15 +++++++++++ packages/react-query/src/useSuspenseQuery.ts | 26 ++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 packages/react-query/src/useSuspenseQuery.ts diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 65606fa8fd..3af53c91a1 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -248,6 +248,7 @@ export interface QueryObserverOptions< */ select?: (data: TQueryData) => TData /** + * @deprecated Use useSuspenseQuery* instead, this option is removed in v5. * If set to `true`, the query will suspend when `status === 'loading'` * and throw errors when `status === 'error'`. * Defaults to `false`. diff --git a/packages/react-query/src/types.ts b/packages/react-query/src/types.ts index 648c0db85c..b4d9c0b7ac 100644 --- a/packages/react-query/src/types.ts +++ b/packages/react-query/src/types.ts @@ -43,6 +43,16 @@ export interface UseQueryOptions< TQueryKey > {} +export interface UseSuspenseQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> extends Omit< + UseQueryOptions, + 'enabled' | 'suspense' | 'placeholderData' + > {} + export interface UseInfiniteQueryOptions< TQueryFnData = unknown, TError = unknown, @@ -68,6 +78,11 @@ export type UseQueryResult< TError = unknown, > = UseBaseQueryResult +export type UseSuspenseQueryResult = Omit< + DefinedQueryObserverResult, + 'isPlaceholderData' | 'promise' +> + export type DefinedUseBaseQueryResult< TData = unknown, TError = unknown, diff --git a/packages/react-query/src/useSuspenseQuery.ts b/packages/react-query/src/useSuspenseQuery.ts new file mode 100644 index 0000000000..0c38bbd51c --- /dev/null +++ b/packages/react-query/src/useSuspenseQuery.ts @@ -0,0 +1,26 @@ +'use client' +import { QueryObserver } from '@tanstack/query-core' +import { useBaseQuery } from './useBaseQuery' +import type { QueryKey } from '@tanstack/query-core' +import type { UseQueryResult, UseSuspenseQueryOptions } from './types' + +// HOOK + +export function useSuspenseQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: UseSuspenseQueryOptions, +): UseQueryResult { + return useBaseQuery( + { + ...options, + enabled: true, + suspense: true, + placeholderData: undefined, + }, + QueryObserver, + ) +} From 5c379444f5bfc34f4dd269786a4504dcf5ee0d55 Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 12:49:16 -0800 Subject: [PATCH 3/6] export useSuspenseQuery --- packages/react-query/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts index b13a86a661..b0e66f5b4a 100644 --- a/packages/react-query/src/index.ts +++ b/packages/react-query/src/index.ts @@ -11,6 +11,7 @@ export * from './types' export { useQueries } from './useQueries' export type { QueriesResults, QueriesOptions } from './useQueries' export { useQuery } from './useQuery' +export { useSuspenseQuery } from './useSuspenseQuery' export { defaultContext, QueryClientProvider, From e86b9485588cc116f7c427719598e7031a81c641 Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 12:57:34 -0800 Subject: [PATCH 4/6] fix isPending for queryobserverrefetecterrorresult --- packages/query-core/src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 3af53c91a1..950a2809ff 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -453,6 +453,7 @@ export interface QueryObserverRefetchErrorResult< isError: true /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: false isRefetchError: true isSuccess: false From 0bfc2d4c2b4a56ae726e0fd6e1754d0e75696e0a Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 14:01:36 -0800 Subject: [PATCH 5/6] fix --- packages/react-query/src/useSuspenseQuery.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-query/src/useSuspenseQuery.ts b/packages/react-query/src/useSuspenseQuery.ts index 0c38bbd51c..b13b876266 100644 --- a/packages/react-query/src/useSuspenseQuery.ts +++ b/packages/react-query/src/useSuspenseQuery.ts @@ -2,7 +2,7 @@ import { QueryObserver } from '@tanstack/query-core' import { useBaseQuery } from './useBaseQuery' import type { QueryKey } from '@tanstack/query-core' -import type { UseQueryResult, UseSuspenseQueryOptions } from './types' +import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' // HOOK @@ -13,7 +13,7 @@ export function useSuspenseQuery< TQueryKey extends QueryKey = QueryKey, >( options: UseSuspenseQueryOptions, -): UseQueryResult { +): UseSuspenseQueryResult { return useBaseQuery( { ...options, @@ -22,5 +22,5 @@ export function useSuspenseQuery< placeholderData: undefined, }, QueryObserver, - ) + ) as UseSuspenseQueryResult } From 6923c9fdef10c13fa52f3e74ecd67d8d0bc0971a Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Tue, 4 Mar 2025 14:38:20 -0800 Subject: [PATCH 6/6] add queryOptions --- packages/react-query/src/index.ts | 5 ++ packages/react-query/src/queryOptions.ts | 58 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 packages/react-query/src/queryOptions.ts diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts index b0e66f5b4a..37540839ed 100644 --- a/packages/react-query/src/index.ts +++ b/packages/react-query/src/index.ts @@ -30,3 +30,8 @@ export { useIsMutating } from './useIsMutating' export { useMutation } from './useMutation' export { useInfiniteQuery } from './useInfiniteQuery' export { useIsRestoring, IsRestoringProvider } from './isRestoring' +export { queryOptions } from './queryOptions' +export type { + DefinedInitialDataOptions, + UndefinedInitialDataOptions, +} from './queryOptions' diff --git a/packages/react-query/src/queryOptions.ts b/packages/react-query/src/queryOptions.ts new file mode 100644 index 0000000000..95f61c1b64 --- /dev/null +++ b/packages/react-query/src/queryOptions.ts @@ -0,0 +1,58 @@ +import type { + InitialDataFunction, + QueryFunction, + QueryKey, +} from '@tanstack/query-core' +import type { UseQueryOptions } from './types' + +export type UndefinedInitialDataOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = UseQueryOptions & { + initialData?: + | undefined + | InitialDataFunction> + | NonUndefinedGuard +} + +type NonUndefinedGuard = T extends undefined ? never : T + +export type DefinedInitialDataOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = Omit, 'queryFn'> & { + initialData: + | NonUndefinedGuard + | (() => NonUndefinedGuard) + queryFn?: QueryFunction +} + +export function queryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: DefinedInitialDataOptions, +): DefinedInitialDataOptions & { + queryKey: TQueryKey +} + +export function queryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: UndefinedInitialDataOptions, +): UndefinedInitialDataOptions & { + queryKey: TQueryKey +} + +export function queryOptions(options: unknown) { + return options +}