useSuspenseInfiniteQuery
1function useSuspenseInfiniteQuery<TQueryFnData, TError = Error, TData = InfiniteData<TQueryFnData, unknown>, TQueryKey extends readonly unknown[] = readonly unknown[], TPageParam = unknown>(options: UseSuspenseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient?: QueryClient): UseSuspenseInfiniteQueryResult<TData, TError>;定义于:packages/react-query/src/useSuspenseInfiniteQuery.ts:102
useSuspenseInfiniteQuery 的选项与 useInfiniteQuery 相同,但排除 throwOnError、enabled 和 placeholderData。
注意:取消(cancellation)不生效。
类型参数
TQueryFnData
TQueryFnData
TError
TError = Error
TData
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam
TPageParam = unknown
参数
options
UseSuspenseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>
要使用的 UseSuspenseInfiniteQueryOptions —— 与 useInfiniteQuery 的选项相同,但排除上述已列出的选项。
options 属性
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
gcTime? |
number |
undefined |
未使用/非活跃缓存数据在内存中保留的毫秒数。当某个查询的缓存变为未使用或非活跃状态时,该缓存数据将在该持续时间后被垃圾回收。当指定不同的垃圾回收时间时,将采用最长的那个。设为 Infinity 将禁用垃圾回收。默认为 5 * 60 * 1000(5 分钟),服务端渲染(SSR)期间则为 Infinity。注意:最大允许时间为约 24 天,受 setTimeout 的 32 位有符号整数延迟限制 —— 参见 timeoutManager.setTimeoutProvider 获取变通方案。 |
getNextPageParam |
(lastPage: TQueryFnData, allPages: TQueryFnData[], lastPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | null | undefined |
undefined |
可设置此函数以自动获取无限查询的下一页游标。该结果还将用于确定 hasNextPage 的值。 |
getPreviousPageParam? |
(firstPage: TQueryFnData, allPages: TQueryFnData[], firstPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | null | undefined |
undefined |
可设置此函数以自动获取无限查询的上一页游标。该结果还将用于确定 hasPreviousPage 的值。 |
initialData? |
| InfiniteData<TQueryFnData, TPageParam> | (() => | InfiniteData<TQueryFnData, TPageParam> | undefined) |
undefined |
若设置,该值将用作查询缓存的初始数据(前提是该查询尚未创建或缓存)。若设为函数,则该函数将在共享/根查询初始化期间调用一次,并需同步返回初始数据。初始数据默认视为过期,除非已设置 staleTime。initialData 会被持久化到缓存中。 |
initialDataUpdatedAt? |
number | (() => number | undefined) |
undefined |
若设置,该值将用作 initialData 本身最近更新的时间(毫秒)。 |
initialPageParam |
TPageParam |
undefined |
当无限查询尚无任何页时,用于起始的页参数。它将作为 queryFn 的 pageParam 传入第一页;之后每一页均使用 getNextPageParam 或 getPreviousPageParam 返回的值。它仅在查询尚无页时生效:一旦存在第一页,重新拉取将从该页自身的参数开始。 |
maxPages? |
number |
undefined |
无限查询数据中最多存储的页数。 |
meta? |
Record<string, unknown> |
undefined |
存储在每个查询上的额外负载。可使用此属性传递可在其他位置使用的附加信息。 |
networkMode? |
"online" | "always" | "offlineFirst" |
'online' |
控制查询是否允许基于当前网络连接状况运行。参见 网络模式(Network Mode) 获取更多信息。 |
notifyOnChangeProps? |
| ( | "error" | "data" | "isError" | "isPending" | "isLoading" | "isLoadingError" | "isRefetchError" | "isSuccess" | "isPlaceholderData" | "status" | "dataUpdatedAt" | "errorUpdatedAt" | "failureCount" | "failureReason" | "errorUpdateCount" | "isFetched" | "isFetchedAfterMount" | "isFetching" | "isInitialLoading" | "isPaused" | "isRefetching" | "isStale" | "isEnabled" | "refetch" | "fetchStatus" | "fetchNextPage" | "fetchPreviousPage" | "hasNextPage" | "hasPreviousPage" | "isFetchNextPageError" | "isFetchingNextPage" | "isFetchPreviousPageError" | "isFetchingPreviousPage")[] | "all" | (() => | "all" | ( | "error" | "data" | "isError" | "isPending" | "isLoading" | "isLoadingError" | "isRefetchError" | "isSuccess" | "isPlaceholderData" | "status" | "dataUpdatedAt" | "errorUpdatedAt" | "failureCount" | "failureReason" | "errorUpdateCount" | "isFetched" | "isFetchedAfterMount" | "isFetching" | "isInitialLoading" | "isPaused" | "isRefetching" | "isStale" | "isEnabled" | "refetch" | "fetchStatus" | "fetchNextPage" | "fetchPreviousPage" | "hasNextPage" | "hasPreviousPage" | "isFetchNextPageError" | "isFetchingNextPage" | "isFetchPreviousPageError" | "isFetchingPreviousPage")[] | undefined) |
undefined |
若设置,组件仅在所列属性发生变更时重新渲染。设为 ['data', 'error'] 时,组件仅在 data 或 error 属性变更时重新渲染。设为 'all' 时,组件将在查询更新时重新渲染。设为函数时,该函数将被执行以计算属性列表。默认为 undefined,此时会自动追踪属性访问,并且组件仅在被追踪的属性之一发生变化时重新渲染。 |
persister? |
(queryFn: (context: QueryFunctionContext<NoInfer<TQueryKey>, TPageParam>) => TQueryFnData | Promise<TQueryFnData>, context: object, query: Query) => TQueryFnData | Promise<TQueryFnData> |
undefined |
此选项可用于将查询结果持久化到外部存储,从而绕过实际调用 queryFn 的需要。适用于跨服务端/客户端边界持久化查询数据等场景。 |
queryFn? |
(context: QueryFunctionContext<TQueryKey, TPageParam>) => TQueryFnData | Promise<TQueryFnData> |
undefined |
skipToken 在此处不允许 —— Suspense Hook 无法渲染“禁用”状态,因此必须始终提供查询函数,除非已定义默认查询函数。 |
queryHash? |
string |
undefined |
queryKey 的哈希形式,使用 queryKeyHashFn(或默认哈希函数)计算得出。内部用作实际缓存键。 |
queryKey |
TQueryKey & object |
undefined |
用于此查询的查询键。查询键将被哈希为稳定哈希值。详见 查询键(Query Keys)。只要 enabled 未设为 false,该键变更时查询将自动更新。 |
queryKeyHashFn? |
(queryKey: TQueryKey) => string |
undefined |
若指定,该函数将用于对 queryKey 进行哈希运算并生成字符串。 |
refetchInterval? |
| number | false | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => number | false | undefined) |
false |
若设为数字,查询将以该频率(毫秒)持续重新拉取。若设为函数,该函数将使用最新数据和查询来计算频率。 |
refetchIntervalInBackground? |
boolean |
false |
若设为 true,查询将在其所在标签页/窗口处于后台时继续重新拉取。 |
refetchOnMount? |
| boolean | "always" | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => boolean | "always") |
true |
若设为 true,查询在挂载时若数据已过期则重新拉取。若设为 false,将禁用同一查询的额外实例触发后台重新拉取。若设为 'always',查询将在挂载时始终重新拉取(除非使用 staleTime: 'static')。若设为函数,该函数将使用最新数据和查询来计算该值。 |
refetchOnReconnect? |
| boolean | "always" | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => boolean | "always") |
undefined |
若设为 true,查询在网络重连时若数据已过期则重新拉取。若设为 false,查询在网络重连时不会重新拉取。若设为 'always',查询将在网络重连时始终重新拉取(除非使用 staleTime: 'static')。若设为函数,该函数将使用最新数据和查询来计算该值。默认为 true,除非 networkMode 为 'always'。 |
refetchOnWindowFocus? |
| boolean | "always" | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => boolean | "always") |
true |
若设为 true,查询在窗口获得焦点时若数据已过期则重新拉取。若设为 false,查询在窗口获得焦点时不会重新拉取。若设为 'always',查询将在窗口获得焦点时始终重新拉取(除非使用 staleTime: 'static')。若设为函数,该函数将使用最新数据和查询来计算该值。 |
retry? |
| number | false | true | ((failureCount: number, error: TError) => boolean) |
undefined |
若为 false,失败的查询默认不再重试。若为 true,失败的查询将无限重试。若设为整数(例如 3),失败的查询将重试直至失败次数达到该数值。若设为函数 (failureCount, error) => boolean,失败的查询将重试直至该函数返回 false。默认客户端为 3,服务端为 0。 |
retryDelay? |
number | ((failureCount: number, error: TError) => number) |
undefined |
此函数接收一个 retryAttempt 整数和实际错误,并返回下次尝试前应延迟的毫秒数。类似 attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000) 的函数应用指数退避;类似 attempt => attempt * 1000 的函数应用线性退避。默认为应用指数退避的函数,上限为 30 秒。 |
retryOnMount? |
| false | true | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => boolean) |
true |
若设为 false,包含错误的查询在挂载时将不会重试。若设为函数,该函数将使用查询来计算该值。 |
select? |
(data: InfiniteData) => TData |
undefined |
此选项可用于转换或选取查询函数返回数据的一部分。它影响返回的 data 值,但不影响存储在查询缓存中的内容。select 函数仅在 data 发生变化,或 select 函数自身引用发生变化时执行。为优化性能,请对函数进行记忆化处理,使其引用在多次调用中保持稳定。 |
staleTime? |
| number | "static" | ((query: Query<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>) => number | "static") |
0 |
数据被视为过期前的毫秒数。若设为 Infinity,数据将永不被视为过期。若设为 'static',数据将永不被视为过期。若设为函数,该函数将使用查询来计算 staleTime。 |
structuralSharing? |
boolean | ((oldData: unknown, newData: unknown) => unknown) |
true |
设为 false 可禁用查询结果之间的结构共享。设为接受旧数据和新数据并返回同类型解析数据的函数,可实现自定义结构共享逻辑。 |
subscribed? |
boolean |
true |
设为 false 可使此观察者取消订阅查询缓存的更新。 |
queryClient?
使用此参数可指定自定义 QueryClient。否则,将使用最近上下文中的 QueryClient。
返回值
UseSuspenseInfiniteQueryResult<TData, TError>
与 useInfiniteQuery 返回的对象相同,但 data 保证已定义,isPlaceholderData 缺失,且 status 为 success 或 error(相应派生标志已设置)。
返回值属性
基于 InfiniteQueryObserverBaseResult 构建。参见上方类型定义了解其变更内容。
备注
同一组件内多个 Suspense 查询调用将串行挂起,导致请求瀑布 —— 每个调用均会阻塞渲染直至其解析完成,因此下一个调用甚至无法启动拉取。在 Suspense 下无法并行化多个无限查询。此外请注意,命令式拉取调用(如 fetchNextPage)可能干扰默认重新拉取行为,导致数据陈旧。请确保仅在响应用户操作时调用这些函数,或添加 hasNextPage && !isFetching 等条件判断。
参见
useInfiniteQuery —— 此 Hook 的非 Suspense 版本。
示例
若拉取失败且尚无缓存数据,查询错误将被抛出,因此 <Suspense> 周围必须包裹错误边界。而失败的后台重新拉取则会继续渲染缓存数据。可使用 QueryErrorResetBoundary 让用户在发生此类错误后重试:
1import { Suspense } from 'react'2import { ErrorBoundary } from 'react-error-boundary'3import {4 QueryErrorResetBoundary,5 useSuspenseInfiniteQuery,6} from '@tanstack/react-query'7 8function Projects() {9 // `data` is guaranteed to be defined here — no `isPending` check needed.10 const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =11 useSuspenseInfiniteQuery({12 queryKey: ['projects'],13 queryFn: ({ pageParam }) => fetchProjects(pageParam),14 initialPageParam: 0,15 getNextPageParam: (lastPage) => lastPage.nextId,16 })17 18 return (19 <div>20 <ul>21 {data.pages.map((page) =>22 page.projects.map((project) => <li key={project.id}>{project.name}</li>),23 )}24 </ul>25 <button26 onClick={() => fetchNextPage()}27 disabled={!hasNextPage || isFetching}28 >29 {isFetchingNextPage30 ? 'Loading more...'31 : hasNextPage32 ? 'Load More'33 : 'Nothing more to load'}34 </button>35 </div>36 )37}38 39function App() {40 return (41 <QueryErrorResetBoundary>42 {({ reset }) => (43 <ErrorBoundary44 onReset={reset}45 fallbackRender={({ resetErrorBoundary }) => (46 <div>47 There was an error!48 <button onClick={() => resetErrorBoundary()}>Try again</button>49 </div>50 )}51 >52 <Suspense fallback={<h1>Loading projects...</h1>}>53 <Projects />54 </Suspense>55 </ErrorBoundary>56 )}57 </QueryErrorResetBoundary>58 )59}