From f25720b2e191ec14d8add00c2d8141df80a8a898 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sun, 22 Sep 2024 03:24:52 +0900 Subject: [PATCH 1/9] refactor: handle type error when skipToken is present in suspense query --- .../src/__tests__/prefetch.test.tsx | 10 +++- .../__tests__/useSuspenseQueries.test-d.tsx | 1 + .../react-query/src/infiniteQueryOptions.ts | 56 +++++++++++++++++++ packages/react-query/src/queryOptions.ts | 28 ++++++++++ packages/react-query/src/types.ts | 26 +++++++-- .../src/useSuspenseInfiniteQuery.ts | 8 +-- .../react-query/src/useSuspenseQueries.ts | 7 --- packages/react-query/src/useSuspenseQuery.ts | 8 +-- 8 files changed, 116 insertions(+), 28 deletions(-) diff --git a/packages/react-query/src/__tests__/prefetch.test.tsx b/packages/react-query/src/__tests__/prefetch.test.tsx index 1b111b57ad..94169b54a5 100644 --- a/packages/react-query/src/__tests__/prefetch.test.tsx +++ b/packages/react-query/src/__tests__/prefetch.test.tsx @@ -12,7 +12,11 @@ import { } from '..' import { createQueryClient, queryKey, renderWithClient, sleep } from './utils' -import type { InfiniteData, UseInfiniteQueryOptions, UseQueryOptions } from '..' +import type { + InfiniteData, + UseSuspenseInfiniteQueryOptions, + UseSuspenseQueryOptions, +} from '..' import type { Mock } from 'vitest' const generateQueryFn = (data: string) => @@ -56,7 +60,7 @@ describe('usePrefetchQuery', () => { const queryClient = createQueryClient({ queryCache }) function Suspended(props: { - queryOpts: UseQueryOptions> + queryOpts: UseSuspenseQueryOptions> children?: React.ReactNode }) { const state = useSuspenseQuery(props.queryOpts) @@ -296,7 +300,7 @@ describe('usePrefetchInfiniteQuery', () => { const Fallback = vi.fn().mockImplementation(() =>
Loading...
) function Suspended(props: { - queryOpts: UseInfiniteQueryOptions< + queryOpts: UseSuspenseInfiniteQueryOptions< T, Error, InfiniteData, diff --git a/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx b/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx index dff0829282..377da4b9f5 100644 --- a/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx +++ b/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx @@ -119,6 +119,7 @@ describe('UseSuspenseQueries config object overload', () => { queries: [ { queryKey: ['withSkipToken'], + // @ts-expect-error TS2345 queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), }, ], diff --git a/packages/react-query/src/infiniteQueryOptions.ts b/packages/react-query/src/infiniteQueryOptions.ts index a63def60e1..4648dcece3 100644 --- a/packages/react-query/src/infiniteQueryOptions.ts +++ b/packages/react-query/src/infiniteQueryOptions.ts @@ -2,7 +2,9 @@ import type { DataTag, DefaultError, InfiniteData, + OmitKeyof, QueryKey, + SkipToken, } from '@tanstack/query-core' import type { UseInfiniteQueryOptions } from './types' @@ -23,6 +25,36 @@ export type UndefinedInitialDataInfiniteOptions< initialData?: undefined } +export type UnusedSkipTokenInfiniteOptions< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +> = OmitKeyof< + UseInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey, + TPageParam + >, + 'queryFn' +> & { + queryFn: Exclude< + UseInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey, + TPageParam + >['queryFn'], + SkipToken + > +} + type NonUndefinedGuard = T extends undefined ? never : T export type DefinedInitialDataInfiniteOptions< @@ -68,6 +100,30 @@ export function infiniteQueryOptions< queryKey: DataTag> } +export function infiniteQueryOptions< + TQueryFnData, + TError = DefaultError, + TData = InfiniteData, + TQueryKey extends QueryKey = QueryKey, + TPageParam = unknown, +>( + options: UnusedSkipTokenInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam + >, +): UnusedSkipTokenInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam +> & { + queryKey: DataTag> +} + export function infiniteQueryOptions< TQueryFnData, TError = DefaultError, diff --git a/packages/react-query/src/queryOptions.ts b/packages/react-query/src/queryOptions.ts index ec1c11aa2c..ff67eecf89 100644 --- a/packages/react-query/src/queryOptions.ts +++ b/packages/react-query/src/queryOptions.ts @@ -2,7 +2,9 @@ import type { DataTag, DefaultError, InitialDataFunction, + OmitKeyof, QueryKey, + SkipToken, } from '@tanstack/query-core' import type { UseQueryOptions } from './types' @@ -15,6 +17,21 @@ export type UndefinedInitialDataOptions< initialData?: undefined | InitialDataFunction> } +export type UnusedSkipTokenOptions< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = OmitKeyof< + UseQueryOptions, + 'queryFn' +> & { + queryFn: Exclude< + UseQueryOptions['queryFn'], + SkipToken + > +} + type NonUndefinedGuard = T extends undefined ? never : T export type DefinedInitialDataOptions< @@ -39,6 +56,17 @@ export function queryOptions< queryKey: DataTag } +export function queryOptions< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: UnusedSkipTokenOptions, +): UnusedSkipTokenOptions & { + queryKey: DataTag +} + export function queryOptions< TQueryFnData = unknown, TError = DefaultError, diff --git a/packages/react-query/src/types.ts b/packages/react-query/src/types.ts index 0979fc5311..b5554aca83 100644 --- a/packages/react-query/src/types.ts +++ b/packages/react-query/src/types.ts @@ -14,6 +14,7 @@ import type { QueryKey, QueryObserverOptions, QueryObserverResult, + SkipToken, } from '@tanstack/query-core' export interface UseBaseQueryOptions< @@ -47,8 +48,13 @@ export interface UseSuspenseQueryOptions< TQueryKey extends QueryKey = QueryKey, > extends OmitKeyof< UseQueryOptions, - 'enabled' | 'throwOnError' | 'placeholderData' - > {} + 'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData' + > { + queryFn: Exclude< + UseQueryOptions['queryFn'], + SkipToken + > +} export interface UseInfiniteQueryOptions< TQueryFnData = unknown, @@ -85,8 +91,20 @@ export interface UseSuspenseInfiniteQueryOptions< TQueryKey, TPageParam >, - 'enabled' | 'throwOnError' | 'placeholderData' - > {} + 'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData' + > { + queryFn: Exclude< + UseInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey, + TPageParam + >['queryFn'], + SkipToken + > +} export type UseBaseQueryResult< TData = unknown, diff --git a/packages/react-query/src/useSuspenseInfiniteQuery.ts b/packages/react-query/src/useSuspenseInfiniteQuery.ts index 9f922c6c30..d64ef0c694 100644 --- a/packages/react-query/src/useSuspenseInfiniteQuery.ts +++ b/packages/react-query/src/useSuspenseInfiniteQuery.ts @@ -1,5 +1,5 @@ 'use client' -import { InfiniteQueryObserver, skipToken } from '@tanstack/query-core' +import { InfiniteQueryObserver } from '@tanstack/query-core' import { useBaseQuery } from './useBaseQuery' import { defaultThrowOnError } from './suspense' import type { @@ -32,12 +32,6 @@ export function useSuspenseInfiniteQuery< >, queryClient?: QueryClient, ): UseSuspenseInfiniteQueryResult { - if (process.env.NODE_ENV !== 'production') { - if (options.queryFn === skipToken) { - console.error('skipToken is not allowed for useSuspenseInfiniteQuery') - } - } - return useBaseQuery( { ...options, diff --git a/packages/react-query/src/useSuspenseQueries.ts b/packages/react-query/src/useSuspenseQueries.ts index 790e72e12a..845917783c 100644 --- a/packages/react-query/src/useSuspenseQueries.ts +++ b/packages/react-query/src/useSuspenseQueries.ts @@ -1,5 +1,4 @@ 'use client' -import { skipToken } from '@tanstack/query-core' import { useQueries } from './useQueries' import { defaultThrowOnError } from './suspense' import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' @@ -192,12 +191,6 @@ export function useSuspenseQueries< { ...options, queries: options.queries.map((query) => { - if (process.env.NODE_ENV !== 'production') { - if (query.queryFn === skipToken) { - console.error('skipToken is not allowed for useSuspenseQueries') - } - } - return { ...query, suspense: true, diff --git a/packages/react-query/src/useSuspenseQuery.ts b/packages/react-query/src/useSuspenseQuery.ts index 9bc53e6fd6..3bf6039d01 100644 --- a/packages/react-query/src/useSuspenseQuery.ts +++ b/packages/react-query/src/useSuspenseQuery.ts @@ -1,5 +1,5 @@ 'use client' -import { QueryObserver, skipToken } from '@tanstack/query-core' +import { QueryObserver } from '@tanstack/query-core' import { useBaseQuery } from './useBaseQuery' import { defaultThrowOnError } from './suspense' import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' @@ -14,12 +14,6 @@ export function useSuspenseQuery< options: UseSuspenseQueryOptions, queryClient?: QueryClient, ): UseSuspenseQueryResult { - if (process.env.NODE_ENV !== 'production') { - if (options.queryFn === skipToken) { - console.error('skipToken is not allowed for useSuspenseQuery') - } - } - return useBaseQuery( { ...options, From ca9bf3d248d8cff022a3bf9a2550290f26de7505 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sun, 22 Sep 2024 21:59:48 +0900 Subject: [PATCH 2/9] test(react-query): add skipToken test for query hooks --- .../src/__tests__/suspense.test-d.tsx | 40 +++++++++---- .../__tests__/useSuspenseQueries.test-d.tsx | 60 +++++++++++++------ 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/packages/react-query/src/__tests__/suspense.test-d.tsx b/packages/react-query/src/__tests__/suspense.test-d.tsx index 6d333a817a..7d14401887 100644 --- a/packages/react-query/src/__tests__/suspense.test-d.tsx +++ b/packages/react-query/src/__tests__/suspense.test-d.tsx @@ -1,7 +1,7 @@ import { describe, expectTypeOf, it } from 'vitest' +import { skipToken } from '@tanstack/query-core' import { useSuspenseQuery } from '../useSuspenseQuery' import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery' -import type { UseSuspenseQueryOptions } from '..' import type { InfiniteData } from '@tanstack/query-core' describe('useSuspenseQuery', () => { @@ -23,6 +23,20 @@ describe('useSuspenseQuery', () => { expectTypeOf(status).toEqualTypeOf<'error' | 'success'>() }) + it('should not allow skipToken in queryFn', () => { + useSuspenseQuery({ + queryKey: ['key'], + // @ts-expect-error + queryFn: skipToken, + }) + + useSuspenseQuery({ + queryKey: ['key'], + // @ts-expect-error + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }) + }) + it('should not allow placeholderData, enabled or throwOnError props', () => { useSuspenseQuery({ queryKey: ['key'], @@ -70,6 +84,20 @@ describe('useSuspenseInfiniteQuery', () => { expectTypeOf(data).toEqualTypeOf>() }) + it('should not allow skipToken in queryFn', () => { + useSuspenseInfiniteQuery({ + queryKey: ['key'], + // @ts-expect-error + queryFn: skipToken, + }) + + useSuspenseInfiniteQuery({ + queryKey: ['key'], + // @ts-expect-error + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }) + }) + it('should not have pending status', () => { const { status } = useSuspenseInfiniteQuery({ queryKey: ['key'], @@ -122,14 +150,4 @@ describe('useSuspenseInfiniteQuery', () => { // @ts-expect-error TS2339 query.isPlaceholderData }) - - it('should not accept skipToken type for queryFn in useSuspenseQuery', () => { - const query: UseSuspenseQueryOptions = { - // @ts-expect-error - queryFn: skipToken, - queryKey: [1], - } - - return query - }) }) diff --git a/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx b/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx index 377da4b9f5..a7770fdf57 100644 --- a/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx +++ b/packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx @@ -89,6 +89,47 @@ describe('UseSuspenseQueries config object overload', () => { expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() }) + it('should not allow skipToken in queryFn', () => { + useSuspenseQueries({ + queries: [ + { + queryKey: ['key'], + // @ts-expect-error + queryFn: skipToken, + }, + ], + }) + + useSuspenseQueries({ + queries: [ + { + queryKey: ['key'], + // @ts-expect-error + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }, + ], + }) + }) + + it('TData should have correct type when conditional skipToken is passed', () => { + const queryResults = useSuspenseQueries({ + queries: [ + { + queryKey: ['withSkipToken'], + // @ts-expect-error + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }, + ], + }) + + const firstResult = queryResults[0] + + expectTypeOf(firstResult).toEqualTypeOf< + UseSuspenseQueryResult + >() + expectTypeOf(firstResult.data).toEqualTypeOf() + }) + describe('custom hook', () => { it('should allow custom hooks using UseQueryOptions', () => { type Data = string @@ -113,23 +154,4 @@ describe('UseSuspenseQueries config object overload', () => { expectTypeOf(data).toEqualTypeOf() }) }) - - it('TData should have correct type when conditional skipToken is passed', () => { - const queryResults = useSuspenseQueries({ - queries: [ - { - queryKey: ['withSkipToken'], - // @ts-expect-error TS2345 - queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), - }, - ], - }) - - const firstResult = queryResults[0] - - expectTypeOf(firstResult).toEqualTypeOf< - UseSuspenseQueryResult - >() - expectTypeOf(firstResult.data).toEqualTypeOf() - }) }) From 91c8ffd00658f525bcde613512db916bf89a04c6 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 10 Oct 2024 04:43:44 +0900 Subject: [PATCH 3/9] fix: merge form main --- .../__tests__/infiniteQueryOptions.test-d.tsx | 23 ++++++++++++++++++- packages/react-query/src/index.ts | 2 ++ .../react-query/src/infiniteQueryOptions.ts | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx index ceedfcaac3..0e621a8028 100644 --- a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -153,7 +153,7 @@ describe('queryOptions', () => { queryClient.prefetchQuery(options) }) - test('allow optional initialData', () => { + test('allow optional initialData function', () => { const initialData: { example: boolean } | undefined = { example: true } const queryOptions = infiniteQueryOptions({ queryKey: ['example'], @@ -168,6 +168,27 @@ describe('queryOptions', () => { queryOptions.initialData expectTypeOf(queryOptions.initialData).toMatchTypeOf< | InitialDataFunction> + | InfiniteData<{ example: boolean }, number> + | undefined + >() + }) + + test('allow optional initialData object', () => { + const initialData: { example: boolean } | undefined = { example: true } + const queryOptions = infiniteQueryOptions({ + queryKey: ['example'], + queryFn: async () => initialData, + // initialData below errors + initialData: initialData + ? { pages: [initialData], pageParams: [] } + : undefined, + getNextPageParam: () => 1, + initialPageParam: 1, + }) + queryOptions.initialData + expectTypeOf(queryOptions.initialData).toMatchTypeOf< + | InitialDataFunction> + | InfiniteData<{ example: boolean }, number> | undefined >() }) diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts index 7d4724bd97..cef5cb54a4 100644 --- a/packages/react-query/src/index.ts +++ b/packages/react-query/src/index.ts @@ -21,11 +21,13 @@ export { queryOptions } from './queryOptions' export type { DefinedInitialDataOptions, UndefinedInitialDataOptions, + UnusedSkipTokenOptions } from './queryOptions' export { infiniteQueryOptions } from './infiniteQueryOptions' export type { DefinedInitialDataInfiniteOptions, UndefinedInitialDataInfiniteOptions, + UnusedSkipTokenInfiniteOptions, } from './infiniteQueryOptions' export { QueryClientContext, diff --git a/packages/react-query/src/infiniteQueryOptions.ts b/packages/react-query/src/infiniteQueryOptions.ts index eed84d1892..b9a0ca8b07 100644 --- a/packages/react-query/src/infiniteQueryOptions.ts +++ b/packages/react-query/src/infiniteQueryOptions.ts @@ -25,6 +25,7 @@ export type UndefinedInitialDataInfiniteOptions< > & { initialData?: | undefined + | NonUndefinedGuard> | InitialDataFunction< NonUndefinedGuard> > From 80fb6989bf8f149af2d20c95874a9443a2f4ee15 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 19:44:48 +0000 Subject: [PATCH 4/9] ci: apply automated fixes --- packages/react-query/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts index cef5cb54a4..ee14798ba8 100644 --- a/packages/react-query/src/index.ts +++ b/packages/react-query/src/index.ts @@ -21,7 +21,7 @@ export { queryOptions } from './queryOptions' export type { DefinedInitialDataOptions, UndefinedInitialDataOptions, - UnusedSkipTokenOptions + UnusedSkipTokenOptions, } from './queryOptions' export { infiniteQueryOptions } from './infiniteQueryOptions' export type { From 9372c8b88d1e4aac283b4e536993f44b4aba374d Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 10 Oct 2024 18:42:19 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat(react-query):=20display=20=E2=80=9Cski?= =?UTF-8?q?pToken=20is=20not=20allowed=E2=80=9D=20message=20in=20suspense?= =?UTF-8?q?=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-query/src/useSuspenseQueries.ts | 7 +++++++ packages/react-query/src/useSuspenseQuery.ts | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/react-query/src/useSuspenseQueries.ts b/packages/react-query/src/useSuspenseQueries.ts index 845917783c..790e72e12a 100644 --- a/packages/react-query/src/useSuspenseQueries.ts +++ b/packages/react-query/src/useSuspenseQueries.ts @@ -1,4 +1,5 @@ 'use client' +import { skipToken } from '@tanstack/query-core' import { useQueries } from './useQueries' import { defaultThrowOnError } from './suspense' import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' @@ -191,6 +192,12 @@ export function useSuspenseQueries< { ...options, queries: options.queries.map((query) => { + if (process.env.NODE_ENV !== 'production') { + if (query.queryFn === skipToken) { + console.error('skipToken is not allowed for useSuspenseQueries') + } + } + return { ...query, suspense: true, diff --git a/packages/react-query/src/useSuspenseQuery.ts b/packages/react-query/src/useSuspenseQuery.ts index 3bf6039d01..7dfdb06477 100644 --- a/packages/react-query/src/useSuspenseQuery.ts +++ b/packages/react-query/src/useSuspenseQuery.ts @@ -1,5 +1,5 @@ 'use client' -import { QueryObserver } from '@tanstack/query-core' +import { QueryObserver, skipToken } from '@tanstack/query-core' import { useBaseQuery } from './useBaseQuery' import { defaultThrowOnError } from './suspense' import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' @@ -14,6 +14,12 @@ export function useSuspenseQuery< options: UseSuspenseQueryOptions, queryClient?: QueryClient, ): UseSuspenseQueryResult { + if (process.env.NODE_ENV !== 'production') { + if ((options.queryFn as any) === skipToken) { + console.error('skipToken is not allowed for useSuspenseQuery') + } + } + return useBaseQuery( { ...options, From 2563143e33be099676b6b405ab41f3f6af78e317 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 10 Oct 2024 19:55:52 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat(react-query):=20display=20=E2=80=9Cski?= =?UTF-8?q?pToken=20is=20not=20allowed=E2=80=9D=20message=20in=20suspense?= =?UTF-8?q?=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-query/src/useSuspenseInfiniteQuery.ts | 8 +++++++- packages/react-query/src/useSuspenseQueries.ts | 6 ------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/react-query/src/useSuspenseInfiniteQuery.ts b/packages/react-query/src/useSuspenseInfiniteQuery.ts index d64ef0c694..614120ca23 100644 --- a/packages/react-query/src/useSuspenseInfiniteQuery.ts +++ b/packages/react-query/src/useSuspenseInfiniteQuery.ts @@ -1,5 +1,5 @@ 'use client' -import { InfiniteQueryObserver } from '@tanstack/query-core' +import { InfiniteQueryObserver, skipToken } from '@tanstack/query-core' import { useBaseQuery } from './useBaseQuery' import { defaultThrowOnError } from './suspense' import type { @@ -32,6 +32,12 @@ export function useSuspenseInfiniteQuery< >, queryClient?: QueryClient, ): UseSuspenseInfiniteQueryResult { + if (process.env.NODE_ENV !== 'production') { + if ((options.queryFn as any) === skipToken) { + console.error('skipToken is not allowed for useSuspenseQuery') + } + } + return useBaseQuery( { ...options, diff --git a/packages/react-query/src/useSuspenseQueries.ts b/packages/react-query/src/useSuspenseQueries.ts index 790e72e12a..026f3a2bbd 100644 --- a/packages/react-query/src/useSuspenseQueries.ts +++ b/packages/react-query/src/useSuspenseQueries.ts @@ -192,12 +192,6 @@ export function useSuspenseQueries< { ...options, queries: options.queries.map((query) => { - if (process.env.NODE_ENV !== 'production') { - if (query.queryFn === skipToken) { - console.error('skipToken is not allowed for useSuspenseQueries') - } - } - return { ...query, suspense: true, From aa7d780b767f2cc99cd302f4843eb83e249f40a9 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 10 Oct 2024 19:57:09 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat(react-query):=20display=20=E2=80=9Cski?= =?UTF-8?q?pToken=20is=20not=20allowed=E2=80=9D=20message=20in=20suspense?= =?UTF-8?q?=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-query/src/useSuspenseQueries.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/react-query/src/useSuspenseQueries.ts b/packages/react-query/src/useSuspenseQueries.ts index 026f3a2bbd..790e72e12a 100644 --- a/packages/react-query/src/useSuspenseQueries.ts +++ b/packages/react-query/src/useSuspenseQueries.ts @@ -192,6 +192,12 @@ export function useSuspenseQueries< { ...options, queries: options.queries.map((query) => { + if (process.env.NODE_ENV !== 'production') { + if (query.queryFn === skipToken) { + console.error('skipToken is not allowed for useSuspenseQueries') + } + } + return { ...query, suspense: true, From c8f16bcfac36b5071ba360cd5c37bd0e5164e744 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 10 Oct 2024 20:03:17 +0900 Subject: [PATCH 8/9] fix(react-query): update error message in useSuspenseInfiniteQuery --- packages/react-query/src/useSuspenseInfiniteQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/useSuspenseInfiniteQuery.ts b/packages/react-query/src/useSuspenseInfiniteQuery.ts index 614120ca23..916e89265a 100644 --- a/packages/react-query/src/useSuspenseInfiniteQuery.ts +++ b/packages/react-query/src/useSuspenseInfiniteQuery.ts @@ -34,7 +34,7 @@ export function useSuspenseInfiniteQuery< ): UseSuspenseInfiniteQueryResult { if (process.env.NODE_ENV !== 'production') { if ((options.queryFn as any) === skipToken) { - console.error('skipToken is not allowed for useSuspenseQuery') + console.error('skipToken is not allowed for useSuspenseInfiniteQuery') } } From b7cd4b1baf38d681542a9118b02669b7b49bb903 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Fri, 11 Oct 2024 19:29:48 +0900 Subject: [PATCH 9/9] test(react-query): add test case --- .../src/__tests__/infiniteQueryOptions.test-d.tsx | 14 +++++++++++++- .../src/__tests__/queryOptions.test-d.tsx | 10 ++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx index fd8bd57917..aa706e71d3 100644 --- a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -1,5 +1,5 @@ import { describe, expectTypeOf, it, test } from 'vitest' -import { QueryClient, dataTagSymbol } from '@tanstack/query-core' +import { QueryClient, dataTagSymbol, skipToken } from '@tanstack/query-core' import { infiniteQueryOptions } from '../infiniteQueryOptions' import { useInfiniteQuery } from '../useInfiniteQuery' import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery' @@ -134,6 +134,18 @@ describe('infiniteQueryOptions', () => { InfiniteData | undefined >() }) + it('should throw a type error when using queryFn with skipToken in a suspense query', () => { + const options = infiniteQueryOptions({ + queryKey: ['key'], + queryFn: + Math.random() > 0.5 ? skipToken : () => Promise.resolve('string'), + getNextPageParam: () => 1, + initialPageParam: 1, + }) + // @ts-expect-error TS2345 + const { data } = useSuspenseInfiniteQuery(options) + expectTypeOf(data).toEqualTypeOf>() + }) test('should not be allowed to be passed to non-infinite query functions', () => { const queryClient = new QueryClient() diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index f833d0db5a..7cacef246b 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -177,6 +177,16 @@ describe('queryOptions', () => { expectTypeOf(data).toEqualTypeOf() }) + it('should throw a type error when using queryFn with skipToken in a suspense query', () => { + const options = queryOptions({ + queryKey: ['key'], + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }) + // @ts-expect-error TS2345 + const { data } = useSuspenseQuery(options) + expectTypeOf(data).toEqualTypeOf() + }) + it('should return the proper type when passed to QueriesObserver', () => { const options = queryOptions({ queryKey: ['key'],