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..950a2809ff 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`. @@ -393,7 +394,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 +419,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 +435,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,7 +451,9 @@ export interface QueryObserverRefetchErrorResult< data: TData error: TError isError: true + /** @deprecated Removed in v5. Use isPending instead */ isLoading: false + isPending: false isLoadingError: false isRefetchError: true isSuccess: false @@ -456,7 +465,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 +506,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 +522,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 +538,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 +554,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 +664,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 +682,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 +698,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 +715,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 +731,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' } diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts index b13a86a661..37540839ed 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, @@ -29,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 +} 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..b13b876266 --- /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 { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' + +// HOOK + +export function useSuspenseQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: UseSuspenseQueryOptions, +): UseSuspenseQueryResult { + return useBaseQuery( + { + ...options, + enabled: true, + suspense: true, + placeholderData: undefined, + }, + QueryObserver, + ) as UseSuspenseQueryResult +}