Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(react-query): backport v5 apis about infinite query #9334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
manudeli wants to merge 9 commits into TanStack:v4
base: v4
Choose a base branch
Loading
from manudeli:react-query/backport-infinite-query
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
9 commits
Select commit Hold shift + click to select a range
9aaf337
feat(react-query): introduce infinite query options and suspense support
manudeli Jul 29, 2025
fb2d620
refactor(react-query): update useSuspenseInfiniteQuery to utilize use...
manudeli Jul 29, 2025
6b61d5e
Merge branch 'v4' into react-query/backport-infinite-query
manudeli Aug 24, 2025
16c08c1
refactor(pr.yml): simplify test job by removing Nx Cloud agent commands
manudeli Aug 24, 2025
22c5ce6
ci(pr.yml): add steps to get base and head commits for `nx affected` ...
manudeli Aug 24, 2025
dc6bd7c
ci(pr.yml): add main-branch-name input for nx-set-shas action
manudeli Aug 24, 2025
8a7abe4
fix(pr.yml): update HEAD commit reference to use pull request SHA
manudeli Aug 24, 2025
c9ddf59
fix(pr.yml): streamline test command by removing unnecessary echo sta...
manudeli Aug 24, 2025
c2da2a2
fix(pr.yml): add quotes around variables in test command for consistency
manudeli Aug 24, 2025
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
8 changes: 3 additions & 5 deletions .github/workflows/pr.yml
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ jobs:
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
- name: Start Nx Agents
run: npx nx-cloud start-ci-run
- name: Setup Tools
uses: tanstack/config/.github/setup@main
- name: Get base and head commits for `nx affected`
uses: nrwl/nx-set-shas@v4.1.2
with:
main-branch-name: 'v4'
- name: Run Tests
run: pnpm run test:pr --parallel=3
- name: Stop Agents
run: npx nx-cloud stop-all-agents
run: pnpm run test:pr --base="${{env.NX_BASE}}" --head="${{github.event.pull_request.head.sha}}"
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
format:
Expand Down
10 changes: 8 additions & 2 deletions packages/query-core/src/types.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,17 @@ export interface InfiniteQueryObserverSuccessResult<
status: 'success'
}

export type DefinedInfiniteQueryObserverResult<
TData = unknown,
TError = unknown,
> =
| InfiniteQueryObserverRefetchErrorResult<TData, TError>
| InfiniteQueryObserverSuccessResult<TData, TError>

export type InfiniteQueryObserverResult<TData = unknown, TError = unknown> =
| DefinedInfiniteQueryObserverResult<TData, TError>
| InfiniteQueryObserverLoadingErrorResult<TData, TError>
| InfiniteQueryObserverLoadingResult<TData, TError>
| InfiniteQueryObserverRefetchErrorResult<TData, TError>
| InfiniteQueryObserverSuccessResult<TData, TError>

export type MutationKey = readonly unknown[]

Expand Down
13 changes: 13 additions & 0 deletions packages/react-query/src/__tests__/infiniteQueryOptions.test.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { infiniteQueryOptions } from '../infiniteQueryOptions'

describe('infiniteQueryOptions', () => {
it('should return the object received as a parameter without any modification.', () => {
const object = {
queryKey: ['key'],
queryFn: () => Promise.resolve(5),
getNextPageParam: () => null,
} as const

expect(infiniteQueryOptions(object)).toStrictEqual(object)
})
})
111 changes: 111 additions & 0 deletions packages/react-query/src/__tests__/infiniteQueryOptions.types.test.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { expectTypeOf } from 'expect-type'
import {
type InfiniteData,
type UseInfiniteQueryResult,
useInfiniteQuery,
useQueryClient,
} from '@tanstack/react-query'

import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'
import { infiniteQueryOptions } from '../infiniteQueryOptions'
import { doNotExecute } from './utils'
import type {
DefinedUseInfiniteQueryResult,
UseSuspenseInfiniteQueryResult,
} from '../types'

const infiniteQuery = {
options: () =>
infiniteQueryOptions({
queryKey: ['key', 1] as const,
queryFn: () => Promise.resolve({ field: 'success' }),
}),
optionsWithInitialData: () =>
infiniteQueryOptions({
queryKey: ['key', 2] as const,
queryFn: () => Promise.resolve({ field: 'success' }),
initialData: () => ({ pageParams: [], pages: [{ field: 'success' }] }),
}),
}

describe('infiniteQueryOptions', () => {
it('should be used with useInfiniteQuery', () => {
doNotExecute(() => {
expectTypeOf(useInfiniteQuery(infiniteQuery.options())).toEqualTypeOf<
UseInfiniteQueryResult<{ field: string }>
>()

expectTypeOf(
useInfiniteQuery({
...infiniteQuery.options(),
select: (data) => ({
pages: data.pages.map(({ field }) => field),
pageParams: data.pageParams,
}),
}),
).toEqualTypeOf<UseInfiniteQueryResult<string>>()

expectTypeOf(
useInfiniteQuery(infiniteQuery.optionsWithInitialData()),
).toEqualTypeOf<DefinedUseInfiniteQueryResult<{ field: string }>>()

expectTypeOf(
useInfiniteQuery({
...infiniteQuery.optionsWithInitialData(),
select: (data) => ({
pages: data.pages.map(({ field }) => field),
pageParams: data.pageParams,
}),
}),
).toEqualTypeOf<DefinedUseInfiniteQueryResult<string>>()

expectTypeOf(
useInfiniteQuery({
queryKey: ['key', 2] as const,
queryFn: () => Promise.resolve({ field: 'success' }),
initialData: () => ({
pages: [{ field: 'success' }],
pageParams: [],
}),
select: (data) => ({
pages: data.pages.map(({ field }) => field),
pageParams: data.pageParams,
}),
}),
).toEqualTypeOf<DefinedUseInfiniteQueryResult<string>>()
})
})
it('should be used with useSuspenseInfiniteQuery', () => {
doNotExecute(() => {
expectTypeOf(
useSuspenseInfiniteQuery(infiniteQuery.options()),
).toEqualTypeOf<UseSuspenseInfiniteQueryResult<{ field: string }>>()

expectTypeOf(
useSuspenseInfiniteQuery({
...infiniteQuery.options(),
select: (data) => ({
pages: data.pages.map(({ field }) => field),
pageParams: data.pageParams,
}),
}),
).toEqualTypeOf<UseSuspenseInfiniteQueryResult<string>>()
})
})
it('should be used with useQueryClient', () => {
doNotExecute(async () => {
const queryClient = useQueryClient()

queryClient.invalidateQueries(infiniteQuery.options())
queryClient.resetQueries(infiniteQuery.options())
queryClient.removeQueries(infiniteQuery.options())
queryClient.cancelQueries(infiniteQuery.options())
queryClient.prefetchQuery(infiniteQuery.options())
queryClient.refetchQueries(infiniteQuery.options())

expectTypeOf(
await queryClient.fetchQuery(infiniteQuery.options()),
).toEqualTypeOf<InfiniteData<{ field: string }>>()
})
})
})
15 changes: 8 additions & 7 deletions packages/react-query/src/__tests__/queryOptions.types.test.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ const queryFn = () => Promise.resolve({ field: 'success' })
describe('queryOptions', () => {
it('should be used with useQuery', () => {
doNotExecute(() => {
const dd = useQuery(
queryOptions({
queryKey,
queryFn,
}),
)
expectTypeOf(dd).toEqualTypeOf<UseQueryResult<{ field: string }>>()
expectTypeOf(
useQuery(
queryOptions({
queryKey,
queryFn,
}),
),
).toEqualTypeOf<UseQueryResult<{ field: string }>>()
expectTypeOf(
useQuery({
...queryOptions({
Expand Down
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { expectTypeOf } from 'expect-type'
import { infiniteQueryOptions, useSuspenseInfiniteQuery } from '..'
import { doNotExecute, sleep } from './utils'
import type { UseSuspenseInfiniteQueryResult } from '..'

import type { InfiniteData } from '@tanstack/react-query'

const queryKey = ['key'] as const
const queryFn = () => sleep(10).then(() => ({ text: 'response' }))

describe('useSuspenseInfiniteQuery', () => {
it('type check', () => {
doNotExecute(() => {
// @ts-expect-error no arg
useSuspenseInfiniteQuery()

useSuspenseInfiniteQuery({
queryKey,
queryFn,
// @ts-expect-error no suspense
suspense: boolean,
})
useSuspenseInfiniteQuery({
queryKey,
queryFn,
// @ts-expect-error no useErrorBoundary
useErrorBoundary: boolean,
})
useSuspenseInfiniteQuery({
queryKey,
queryFn,
// @ts-expect-error no enabled
enabled: boolean,
})
useSuspenseInfiniteQuery({
queryKey,
queryFn,
// @ts-expect-error no placeholderData
placeholderData: 'placeholder',
})
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
useSuspenseInfiniteQuery({
queryKey,
queryFn,
// @ts-expect-error no isPlaceholderData
}).isPlaceholderData
useSuspenseInfiniteQuery({
queryKey,
queryFn,
//@ts-expect-error no networkMode
networkMode: 'always',
})

const infiniteQuery = useSuspenseInfiniteQuery({ queryKey, queryFn })
expectTypeOf(infiniteQuery).toEqualTypeOf<
UseSuspenseInfiniteQueryResult<{ text: string }>
>()
expectTypeOf(infiniteQuery.data).toEqualTypeOf<
InfiniteData<{ text: string }>
>()
expectTypeOf(infiniteQuery.status).toEqualTypeOf<'error' | 'success'>()

const selectedInfiniteQuery = useSuspenseInfiniteQuery({
queryKey,
queryFn,
select: (data) => ({
pages: data.pages.map(({ text }) => text),
pageParams: data.pageParams,
}),
})
expectTypeOf(selectedInfiniteQuery).toEqualTypeOf<
UseSuspenseInfiniteQueryResult<string>
>()
expectTypeOf(selectedInfiniteQuery.data).toEqualTypeOf<
InfiniteData<string>
>()
expectTypeOf(selectedInfiniteQuery.status).toEqualTypeOf<
'error' | 'success'
>()

const options = infiniteQueryOptions({
queryKey,
queryFn,
})

const infiniteQueryWithOptions = useSuspenseInfiniteQuery(options)
expectTypeOf(infiniteQueryWithOptions).toEqualTypeOf<
UseSuspenseInfiniteQueryResult<{ text: string }>
>()
expectTypeOf(infiniteQueryWithOptions.data).toEqualTypeOf<
InfiniteData<{ text: string }>
>()
expectTypeOf(infiniteQueryWithOptions.status).toEqualTypeOf<
'error' | 'success'
>()

const selectedInfiniteQueryWithOptions = useSuspenseInfiniteQuery({
...options,
select: (data) => ({
pages: data.pages.map(({ text }) => text),
pageParams: data.pageParams,
}),
})
expectTypeOf(selectedInfiniteQueryWithOptions).toEqualTypeOf<
UseSuspenseInfiniteQueryResult<string>
>()
expectTypeOf(selectedInfiniteQueryWithOptions.data).toEqualTypeOf<
InfiniteData<string>
>()
expectTypeOf(selectedInfiniteQueryWithOptions.status).toEqualTypeOf<
'error' | 'success'
>()
})
})
})
6 changes: 6 additions & 0 deletions packages/react-query/src/index.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { useQueries } from './useQueries'
export type { QueriesResults, QueriesOptions } from './useQueries'
export { useQuery } from './useQuery'
export { useSuspenseQuery } from './useSuspenseQuery'
export { useSuspenseInfiniteQuery } from './useSuspenseInfiniteQuery'
export { useSuspenseQueries } from './useSuspenseQueries'
export type {
SuspenseQueriesResults,
Expand All @@ -22,6 +23,11 @@ export type {
DefinedInitialDataOptions,
UndefinedInitialDataOptions,
} from './queryOptions'
export { infiniteQueryOptions } from './infiniteQueryOptions'
export type {
DefinedInitialDataInfiniteOptions,
UndefinedInitialDataInfiniteOptions,
} from './infiniteQueryOptions'
export {
defaultContext,
QueryClientProvider,
Expand Down
Loading
Loading

AltStyle によって変換されたページ (->オリジナル) /