服务端状态缓存

共 34 题
📑 题目列表 34 题
#
★★★

1. useSuspenseQuery 与 React 19 use()/Suspense 的集成边界,流式渲染与错误边界的工程协作

请解释 useSuspenseQuery 与 React 19 的 use()/Suspense 的集成边界,以及流式渲染与错误边界的工程协作?

  • useSuspenseQuery 的 Suspense 集成
  • React 19 use() 读取 promise
  • 错误边界与流式渲染的协作

useSuspenseQuery 让查询处于 pending 时抛出 promise,触发最近的 Suspense 边界显示 fallback。React 19 的 use() 可直接在组件中读取 promise,配合 Suspense 实现数据获取的语义化。流式渲染下,Suspense 边界可让 HTML 先输出已就绪的部分,未就绪部分用占位并随后流式补全。错误边界捕获 useSuspenseQuery 抛出的错误,应放在 Suspense 外层或作为边界。工程协作要点:设置合适的 Suspense fallback 与 ErrorBoundary 层级,避免整页阻塞或错误冒泡到根导致白屏。

Suspense 的边界是"等待与错误的隔离线"。useSuspenseQuery 把数据获取变成可被 Suspense 暂停的异步,流式渲染提升首屏体验,错误边界处理失败路径。两者协调决定加载与错误体验。

#
★★★

2. Persisted Query Client(localStorage/OPFS)

请解释 TanStack Query 的 Persisted Query Client,以及它在 localStorage/OPFS 中的持久化?

  • PersistQueryClient 插件
  • localStorage 与 OPFS 的持久化
  • 缓存幂等与版本

TanStack Query 提供 PersistQueryClient 插件,把查询缓存持久化到 storage,刷新后恢复缓存,避免重复请求。持久化目标可选 localStorage(简单、容量约 5MB,同步)或 OPFS(Origin Private File System,容量更大、异步、适合大缓存)。持久化需注意:缓存数据可能过期,需结合 staleTime 判断;存 caches 的版本号(bustCache)以防 schema 变化导致旧缓存损坏;恢复缓存后需验证数据有效性。工程取舍:localStorage 简单但容量小,OPFS 容量大但异步、实现复杂。

持久化缓存让"刷新不丢数据",但需处理缓存版本与失效。localStorage 适合小缓存,OPFS 适合对性能和容量有要求的场景。核心是缓存数据与业务数据的一致性。

#
★★★

3. TanStack Query 的 select 选项在数据转换与缓存命中的应用

请解释 TanStack Query 的 select 选项在数据转换与缓存命中中的应用?

  • select 的转换作用
  • 缓存命中与派生数据
  • 与 useMemo 的关系

select 选项在查询结果返回后对数据进行转换,供组件消费。转换结果可被缓存,避免每次渲染重复计算,且原始数据仍保存在缓存中,供其他组件用不同 select 复用。select 常用于格式化、筛选、映射字段。它与 useMemo 的关系:select 是查询层的数据转换,useMemo 是组件层的派生计算;select 还能配合结构共享(structuralSharing)减少不必要更新。注意 select 函数需保证引用稳定,否则可能触发额外重渲染。

select 的工程价值在于"一份原始缓存 + 多种展示视图",派生数据在查询层计算,提升缓存复用率。select 结果引用稳定是关键,避免重复计算或重渲染。

const { data } = useQuery({
  queryKey: ['users'],
  queryFn: fetchUsers,
  select: (users) => users.filter((u) => u.active).map((u) => u.name),
});
#
★★★

4. Optimistic Update 与 revalidation 的实现

请解释 Optimistic Update(乐观更新)与 revalidation 的实现方式?

  • 乐观更新与回滚
  • revalidation(重新验证)
  • 与服务器一致的最终一致性

乐观更新指在服务端响应前先更新本地缓存,让 UI 立即反馈,提高感知性能。实现上用 setQueryData 临时写入乐观值,mutation 成功后用真实响应覆盖,失败则回滚。revalidation 指 mutation 成功后调用 invalidateQueries 重新获取服务端数据,确保缓存与服务器一致。两者配合:乐观更新提供即时反馈,revalidation 保证最终一致性;失败时的回滚恢复原状。关键是把乐观值、回滚值、真实值三者正确管理。

乐观更新是"先写后验",revalidation 是"后验同步"。价值在于平衡即时反馈与数据一致性,但需处理并发与回滚,避免乐观值污染缓存。

#
★★★

5. 依赖 hydration 的请求级 QueryClient 模式

请解释依赖 hydration 的请求级 QueryClient 模式,以及它在 SSR 中的应用?

  • 请求级 QueryClient 单例
  • queryClient 的 hydration/dehydration
  • SSR 数据预取与客户端注水

在 SSR 中,模块级 QueryClient 单例会被多个请求共享,导致跨请求数据串扰。请求级 QueryClient 模式是每个请求创建独立的 QueryClient 实例,隔离数据。服务端用 prefetchQuery 预取数据,配合 dehydrate 把缓存序列化注入 HTML;客户端用 hydrate 恢复缓存,避免重复请求。hydration 保证服务端渲染的数据在客户端直接可用,实现首屏一致。该模式是 Next.js/Remix 中 TanStack Query SSR 的标准做法。

请求级隔离解决"并发请求串数据",hydration 解决"服务端数据到客户端复用"。两者结合让 SSR 数据预取与客户端缓存无缝衔接,提升首屏体验与一致性。

#
★★★

6. 客户端缓存的内存上限与淘汰策略(gcTime、容量清理)在长会话 SPA 的工程取舍

请解释客户端缓存的内存上限与淘汰策略(gcTime、容量清理)在长会话 SPA 中的工程取舍?

  • gcTime 的内存回收
  • 缓存容量上限与清理
  • 长会话 SPA 的内存管理

TanStack Query 用 gcTime 控制缓存被回收前保留的时间(默认 5 分钟),但缓存本身没有严格的内存上限,长会话 SPA 中大量 queryKey 堆积可能造成内存增长。须主动管理:合理设置 gcTime、对大型数据禁用缓存或按需清理、监控缓存数量、利用结构共享减少重复。工程取舍:gcTime 太短频繁重新请求,太长内存占用高;需在"命中率"与"内存"间平衡,必要时实现容量上限与 LRU 清理。

长会话 SPA 的数据量随用户操作累积,缓存是"空间换时间"。需结合数据规模、缓存命中率、gcTime 与主动清理策略,控制内存占用,避免性能劣化。

#
★★★

7. RTK Query 与 TanStack Query 在 Redux 生态内外的工程取舍

请对比 RTK Query 与 TanStack Query 在 Redux 生态内外的工程取舍?

  • RTK Query 与 Redux 的深度集成
  • TanStack Query 的框架无关
  • 选型依据

RTK Query 是 Redux Toolkit 内置的数据获取方案,与 Redux store 深度集成,查询状态直接进入 Redux,配合 DevTools 可调试。TanStack Query 是独立的数据获取库,不依赖 Redux,与 React、Vue、Solid 等框架集成,API 更专注于缓存与同步。取舍:已在 Redux 生态中且希望查询状态与全局状态统一、用同一套调试工具时选 RTK Query;希望轻量、框架独立、专注服务端缓存时选 TanStack Query。RTK Query 与 Redux 绑定带来一致性但增加耦合,TanStack Query 更灵活。

取舍核心是"是否愿意把服务端状态并入 Redux"。RTK Query 一体化但耦合,TanStack Query 解耦灵活。团队已有 Redux 且需要统一状态可考虑 RTK Query,否则 TanStack Query 更轻。

#
★★★

8. SWR 的 mutation + optimistic update + rollback 机制在点赞/表单的工程价值

请解释 SWR 的 mutation + optimistic update + rollback 机制在点赞/表单等场景的工程价值?

  • useSWRMutation 与 mutate
  • optimistic data 与 rollback
  • 点赞/表单的即时反馈

SWR 的 mutate 可临时用 optimistic data 覆盖缓存,UI 立即反映预期结果,服务端响应后回填真实数据;失败时用 rollback 恢复到原值。点赞场景:点击后立即显示已点赞,请求失败则回滚。表单场景:提交后立即显示成功态,失败回滚并提示。工程价值在于把"即时反馈 + 最终一致 + 失败恢复"封装为 mutation 的标准流程,避免手写 loading/error/rollback 状态机。

optimistic update 提升感知性能,rollback 保证失败路径安全。SWR 把 mutate 的乐观值与回滚封装,让点赞/表单这类高频交互反馈更流畅。

#
★★★

9. TanStack Query v5 的 queryKey 序列化、staleTime/gcTime 缓存生命周期工程价值

请解释 TanStack Query v5 的 queryKey 序列化与 staleTime/gcTime 缓存生命周期工程价值?

  • queryKey 序列化规则
  • staleTime/gcTime 生命周期
  • 缓存命中的工程价值

v5 中 queryKey 是数组,元素可以是字符串、数字、对象等,序列化时对象按稳定顺序(key 排序)比较,保证同为等价对象命中同一缓存。staleTime 控制数据多久后过期,过期前读取走缓存;gcTime 控制不再被引用后缓存保留多久再回收。两者共同定义缓存生命周期:fresh 期间不请求,stale 后按需重新验证,gc 回收后释放内存。工程价值在于通过合理配置提高缓存命中率、减少请求、控制内存。

序列化保证"同一请求"命中"同一缓存",staleTime/gcTime 定义数据从新鲜到回收的生命周期。v5 的稳定序列化避免引用变化导致的缓存失效,是缓存命中的基础。

#
★★★

10. SWR 的 mutate 全局刷新与 revalidate 边界

请解释 SWR 的 mutate 全局刷新与 revalidate 的边界?

  • mutate 按 key 更新缓存
  • 全局刷新与定向刷新
  • revalidate 与 mutate 的关系

SWR 的 mutate 可更新指定 key 的缓存数据,也可通过重新验证(revalidate)从服务器拉取最新数据。全局刷新(如 mutate() 无 key 或使用 cache 遍历)可刷新所有 key,但成本高、易过度请求。定向刷新(mutate(key))只刷新相关 key。两者边界:mutate 是"写缓存/触发重验",revalidate 是"从服务器重新获取"。工程上应优先定向 mutate,避免全量刷新导致的不必要请求。

mutate 与 revalidate 的边界在于"改缓存"与"重新拉取"。全局刷新是双刃剑,需谨慎使用;定向刷新精确控制刷新范围,是工程实践的主流。

#
★★★

11. TanStack Query 的 queryClient.getQueryData/setQueryData 在跨组件通信的工程价值

请解释 TanStack Query 的 queryClient.getQueryData/setQueryData 在跨组件通信中的工程价值?

  • getQueryData/setQueryData 读取与写入缓存
  • 跨组件共享缓存数据
  • 与 props 提升的对比

queryClient 是全局单例,getQueryData 读取指定 queryKey 的缓存数据,setQueryData 写入或更新缓存,无需组件订阅即可操作。跨组件通信时,一个组件可 setQueryData 更新缓存,其他组件通过 useQuery 读取同一 key 自动响应,无需 props 钻透或 context。工程价值在于把"共享数据"放在查询缓存中,组件通过 queryKey 互相通信,减少状态提升与 prop drilling,且数据天然与服务器同步。

查询缓存本身就是"共享数据层"。getQueryData/setQueryData 提供命令式读写,配合 useQuery 的声明式订阅,实现跨组件数据共享与同步。

#
★★★

12. Query 与 Server Components 的职责边界

请说明客户端 Query 库与 Server Components 的职责边界?

  • Server Components 的服务端数据获取
  • 客户端 Query 的服务端状态缓存
  • 职责划分

Server Components(RSC)在服务端执行数据获取,直接把数据渲染进 HTML,适合首屏、无需交互的静态数据;客户端 Query 库(如 TanStack Query)在客户端管理服务端状态缓存,负责动态数据、交互后的刷新、乐观更新、失效重验。职责边界:RSC 负责"服务端数据获取与初始渲染",Query 负责"客户端缓存与同步"。RSC 数据可 hydration 到客户端,但动态更新仍需客户端 Query。实践中 RSC 取首屏数据,Query 处理用户交互后的数据变化。

边界是"取数的时机与位置"。RSC 在服务端取数、无客户端往返;Query 在客户端取数、支持缓存与实时同步。两者协作:RSC 提供初始数据,Query 接管后续更新。

#
★★★

13. SWR 与 TanStack Query 的能力对比

请对比 SWR 与 TanStack Query 的能力差异?

  • 缓存与失效机制
  • 功能丰富度(无限查询、并发、DevTools)
  • 选型考虑

SWR 与 TanStack Query 都是基于 stale-while-revalidate 的服务端状态库。SWR 简洁轻量、API 少、学习成本低,擅长基本的缓存与重验证。TanStack Query 功能更丰富:支持无限查询(useInfiniteQuery)、乐观更新、离线持久化、DevTools、Query 生命周期细粒度控制、更完善的类型。取舍:轻量项目、追求简单用 SWR;复杂场景(无限滚动、乐观更新、深度调试)用 TanStack Query。两者都解决"服务端状态缓存",差异在功能深度与生态。

能力对比核心是"功能深度"与"简洁度"。SWR 以简单取胜,TanStack Query 以全面闻名。选型取决于项目复杂度与团队对功能的需求。

#
★★★

14. Redux Toolkit 的 listenerMiddleware 与 URL 状态/路由器的协作

请解释 Redux Toolkit 的 listenerMiddleware 与 URL 状态/路由器的协作?

  • listenerMiddleware 监听 action
  • 与 URL/路由同步
  • 副作用触发

listenerMiddleware 是 RTK 提供的副作用中间件,可监听特定 action 触发副作用(如导航、请求、持久化)。与 URL/路由协作时,可在匹配到某 action 时调用 router push/replace 更新 URL,或在路由变化时同步 dispatch 到 store。它也常替代手写 thunk 处理"某 action 后更新 URL、某状态变化后同步路由"等场景。工程价值在于把副作用集中声明式管理,避免在组件中散落重复逻辑。

listenerMiddleware 提供"action 驱动的副作用"模型,与 URL 状态同步是典型应用。相比在组件 useEffect 中监听,中间件集中、可测、可复用。

#
★★★

15. Apollo Client + GraphQL 在缓存归一化(normalized cache)

请解释 Apollo Client + GraphQL 的缓存归一化(normalized cache)机制?

  • 归一化存储与类型主键
  • 缓存重建与引用
  • 与本地状态协作

Apollo Client 将 GraphQL 查询结果按实体(type + id)归一化存储到缓存,而不是存整棵查询树。这样同一实体被多次查询时只存一份,引用指向同一份,避免数据重复与不一致。typePolicies 可自定义 keyFields 指定主键。读取时按字段从缓存重建查询结果(normalization + dataIdFromObject)。归一化缓存让不同查询共享实体、更新一处全局生效,但需处理 merge 冲突与缓存引用完整性。

normalized cache 的价值是"实体唯一、更新传播"。它让一个实体被多处引用时保持一致,但需要正确的类型主键与 merge 策略,否则缓存会错乱。

#
★★★

16. SWR 的 fallbackData/fallback 在 SSR 与初始化的工程价值

请解释 SWR 的 fallbackData/fallback 在 SSR 与初始化中的工程价值?

  • fallbackData 的初始数据
  • fallback 的 SSR 注入
  • 首屏无请求

fallbackData 为 useSWR 提供初始数据,组件首次渲染直接使用,避免请求期间的 loading。fallback 用于 SSR:在服务端预取数据后,通过 fallback 对象注入到 SWRConfig,客户端 hydrate 时直接读取,避免首屏重复请求并保证一致性。工程价值在于服务端渲染的数据无缝传递到客户端,减少首屏空白与请求,同时保持数据新鲜。

fallbackData 是"初始数据",fallback 是"全局初始数据注入"。SSR 场景下先在服务端取数,再以 fallback 注入客户端,实现"无请求首屏"与 hydration 一致性。

#
★★

17. stale-while-revalidate HTTP 缓存语义与 TanStack Query 的协同工程价值

请解释 stale-while-revalidate 的 HTTP 缓存语义与 TanStack Query 的协同工程价值?

  • SWR 缓存语义
  • HTTP 缓存头协同
  • 双层缓存价值

stale-while-revalidate 是 HTTP 缓存策略:返回过期的缓存数据的同时后台重新验证,更新后替换。TanStack Query 的缓存机制与之类似,但作用于应用层。协同价值:HTTP 层(Cache-Control: stale-while-revalidate)减少网络传输,应用层(TanStack Query)管理数据新鲜度与重验证。两者配合可实现"快速响应 + 最终一致",减少服务器压力与用户等待。工程上可让 HTTP 缓存与查询缓存叠加,分层优化。

SWR 语义是"旧数据可用、后台更新"。TanStack Query 在应用层实现该语义,HTTP 层再加速网络,双层协同提升缓存命中与响应速度。

#
★★

18. Query 的 Devtools 与 setQueryData 在 mutation 错误的协作

请说明 Query 的 DevTools 与 setQueryData 在 mutation 错误处理中的协作?

  • DevTools 查看缓存状态
  • setQueryData 的乐观更新
  • mutation 错误回滚

DevTools 可实时查看缓存中的数据、queryKey、状态(fresh/stale/fetching),辅助调试。mutation 错误处理中,常用 setQueryData 先做乐观更新,错误时回滚或恢复。协作:DevTools 观察乐观数据是否被覆盖、错误后缓存是否回滚正确,帮助定位 mutation 的缓存变更问题。setQueryData 提供命令式缓存写入,配合 DevTools 的可视化,可精确调试"乐观更新未生效/回滚失败"等缓存问题。

setQueryData 提供"写缓存"能力,DevTools 提供"看缓存"能力。两者结合让 mutation 的缓存变更流程可观测、可调试,是工程实践的重要工具。

#
★★

19. Query 的 placeholderData: keepPreviousData 在分页 UX 的工程价值

请解释 Query 的 placeholderData: keepPreviousData 在分页 UX 中的工程价值?

  • keepPreviousData 保留上一页数据
  • 避免 loading 闪烁
  • 分页体验优化

placeholderData: keepPreviousData 让切换查询参数(如分页)时,先用上一页的数据作为占位渲染,新数据到达后替换。这避免了分页切换时的 loading 闪烁(旧数据突然消失、loading 出现),UI 更平滑。工程价值在于优化分页体验:用户翻页时看到旧数据保持,新数据到达后无缝更新,减少视觉跳动。类似场景还有筛选、搜索等高频参数切换。

keepPreviousData 的本质是"占位数据 + 平滑过渡"。它让请求期间不出现空白,改善感知性能,是分页/筛选 UX 的重要手段。

#
★★

20. Mutation、Infinite Query、Suspense Query 的场景

请说明 Mutation、Infinite Query、Suspense Query 各自的适用场景?

  • mutation 的写操作场景
  • Infinite Query 的无限滚动
  • Suspense Query 的加载编排

useMutation 用于写操作(增删改),管理 pending/error/success 状态,配合乐观更新与失效缓存。useInfiniteQuery 用于无限滚动/分页加载,维护页游标与"加载更多",自动拼接数据。useSuspenseQuery 用于配合 Suspense 的读取场景,把数据获取编排进 Suspense,提供声明式加载与错误边界。三者划分:mutation 处理写,Infinite Query 处理分页读,Suspense Query 处理并发读的加载编排。

场景划分:写操作用 mutation,滚动分页用 Infinite Query,Suspense 编排用 Suspense Query。理解各自侧重点避免误用,提升编码准确性。

#
★★

21. TanStack Query 的 useMutation 在乐观更新与回滚的工程实践

请解释 TanStack Query 的 useMutation 在乐观更新与回滚中的工程实践?

  • onMutate 乐观更新与快照
  • onError 回滚
  • onSettled 失效刷新

useMutation 的乐观更新实践:onMutate 中先取消相关查询(cancelQueries)、用 setQueryData 写入乐观值、保存旧数据快照;onError 中读取快照回滚(setQueryData 恢复旧值);onSettled 中 invalidateQueries 重新获取确保一致。工程价值在于把"先写后验、失败回滚"封装为 mutation 的标准流程,保证 UI 即时反馈与数据一致性。

乐观更新的关键是"快照保存与回滚"。onMutate 存快照、onError 回滚、onSettled 重验,构成了乐观更新的完整闭环。

#
★★

22. 乐观更新的并发冲突处理与 mutation scope/串行化,多用户编辑同一数据的冲突解决策略

请解释乐观更新的并发冲突处理,以及 mutation scope/串行化在多用户编辑同一数据时的冲突解决策略?

  • 并发乐观更新的冲突
  • mutation scope 串行化
  • 冲突解决策略

多用户同时编辑同一数据时,乐观更新可能基于过期快照提交,导致丢失更新。策略包括:一是 mutation scope 串行化,同一 scope 的 mutation 排队执行,避免并发覆盖;二是基于版本号/时间戳的冲突检测,提交时校验版本,冲突则引发冲突信号;三是乐观更新后立即 revalidate,用服务器数据覆盖;四是合并策略(如 last-write-wins 或字段级合并)。工程取舍是在"即时反馈"与"一致性"间平衡,必要时提示用户冲突。

并发冲突是乐观更新的固有风险。串行化牺牲部分并发保证顺序,版本检测提供冲突信号,revalidate 保证最终一致。需按业务要求选择策略。

#
★★

23. 查询取消(AbortSignal)与竞态条件处理,路由切换/组件卸载时请求自动取消的工程实现

请解释查询取消(AbortSignal)与竞态条件处理,以及路由切换/组件卸载时请求自动取消的工程实现?

  • AbortSignal 传入 fetch
  • 组件卸载/路由切换取消请求
  • 竞态条件避免

TanStack Query 会为 queryFn 传入 AbortSignal,queryFn 中若用 fetch 可直接传入 signal,实现请求取消。当组件卸载或 queryKey 变化时,Query 会取消进行中的请求。路由切换时,旧页面的请求被取消,避免响应后更新已卸载组件(竞态条件)。工程实现要点:queryFn 必须接收 signal 并转发给 fetch,才能被取消;取消后不更新状态,避免内存泄漏与僵尸请求。

竞态条件指"旧请求后返回覆盖新请求结果"。AbortSignal 取消机制让旧请求在路由切换时被终止,防止过期响应污染状态。

#
★★

24. TanStack Query 的 invalidateQueries 在数据同步的工程应用

请解释 TanStack Query 的 invalidateQueries 在数据同步中的工程应用?

  • invalidateQueries 的失效与重取
  • 按前缀精确失效
  • 数据同步场景

invalidateQueries 使指定 queryKey 的查询失效并重新获取,是数据同步的核心手段。mutation 成功后失效相关查询,使缓存与服务器一致;也可精确指定前缀(如 ['posts'])失效一组查询。工程应用:表单提交后刷新列表、操作后同步详情、跨模块数据同步。配合 refetchType 可控制是否立即重取。invalidateQueries 让"数据变更后自动刷新"成为声明式操作。

invalidateQueries 是"失效+重取"的组合。按前缀精确失效避免过度刷新,是数据同步与缓存一致性的基础能力。

#
★★

25. TanStack Query 的 useInfiniteQuery 在无限滚动分页的现代实践

请解释 TanStack Query 的 useInfiniteQuery 在无限滚动分页中的现代实践?

  • getNextPageParam 分页游标
  • 数据拼接与状态
  • 无限滚动触发

useInfiniteQuery 管理分页数据,getNextPageParam 根据上一页响应计算下一页参数(或返回 undefined 表示没有更多)。返回的 data.pages 是各页数据数组,fetchNextPage 加载下一页,hasNextPage 表示是否还有更多。无限滚动在滚动到底部时调用 fetchNextPage,配合 IntersectionObserver 实现。工程价值:封装分页游标、自动拼接、处理加载更多与结束状态,是现代无限滚动列表的标准方案。

useInfiniteQuery 把"分页游标、拼接、加载更多"封装成标准 API。getNextPageParam 决定分页逻辑,fetchNextPage/hasNextPage 驱动滚动加载。

#
★★

26. RTK Query 在 Redux Toolkit 中的服务端状态管理的工程应用

请解释 RTK Query 在 Redux Toolkit 中的服务端状态管理工程应用?

  • createApi 定义端点
  • 缓存/失效/标签
  • 与 Redux 集成

RTK Query 通过 createApi 定义一组查询/变更端点,自动生成 hooks、缓存管理、请求状态。它与 Redux store 集成,查询状态存于 store,支持 tags(标签)机制:mutation 成功后按 tag 使相关查询失效。工程应用:把服务端状态作为 Redux 的一部分统一管理,配合 DevTools 调试,支持乐观更新、轮询、缓存。它把"服务端数据获取"纳入 Redux 生态,减少手写 action/thunk。

RTK Query 的价值是与 Redux 一体化,查询/缓存/失效状态都可观测可调试。tags 机制实现数据变更后自动刷新,是服务端状态管理的核心。

#
★★

27. TanStack Query 的 prefetchQuery 在路由预加载的工程实践

请解释 TanStack Query 的 prefetchQuery 在路由预加载中的工程实践?

  • prefetchQuery 预取数据
  • 路由 loader 预加载
  • 提升导航体验

prefetchQuery 在用户导航前预取数据并写入缓存,导航后组件直接命中缓存,无需等待请求。工程实践:在路由 loader(如 React Router loader、TanStack Router loader)中调用 prefetchQuery,导航时预取;也可在 hover 链接时预取。配合 staleTime 避免预取后被立即淘汰。工程价值是显著减少导航等待时间,提升页面切换体验。

prefetchQuery 是"导航前缓存"。把预取放在路由 loader 或用户交互时机,让数据在需要时已就绪,是前端性能优化的常见手段。

#
★★

28. TanStack Query 在 SSR(Next.js、Remix)

请解释 TanStack Query 在 SSR(Next.js、Remix)中的应用?

  • 请求级 QueryClient
  • 服务端预取与客户端 hydrate
  • 与框架数据加载器协作

SSR 中需用请求级 QueryClient 避免串数据。Next.js 中常在 SSR 组件中 prefetchQuery 预取,配合 dehydrate 到客户端、hydrate 恢复。Remix 中常用 loader 预先取数,把数据传给客户端 Query 作为 initialData。关键点:服务端预取数据在客户端复用,避免重复请求与 hydration mismatch;配合 Suspense 与流式渲染。工程价值是首屏数据一致、减少客户端请求。

SSR 的核心是"服务端取数、客户端复用"。请求级隔离 + dehydrate/hydrate 或 initialData 实现数据无缝传递,保证 SSR 与客户端一致性。

#
★★

29. TanStack Query 的 dependent queries(enabled)在条件请求的应用

请解释 TanStack Query 的 dependent queries(enabled 选项)在条件请求中的应用?

  • enabled 控制查询激活
  • 依赖前序查询
  • 条件请求场景

enabled 选项控制查询是否自动执行,可用于条件请求(dependent queries)。当某查询依赖另一查询的结果时,用 enabled: !!data 或 enabled: !!id 让查询在依赖就绪后才执行。例如先获取用户,再根据用户 id 获取其订单。enabled 为 false 时查询不触发,成为"闲置"状态。工程价值:避免在依赖缺失时发起无效请求,实现查询间的顺序依赖。

enabled 是"条件执行"开关。dependent queries 通过 enabled 把"依赖前序数据"表达为查询配置,避免手动条件判断,提升代码清晰度。

#
★★

30. TanStack Query 的 retry 与 retryDelay 在网络重试的工程取舍

请解释 TanStack Query 的 retry 与 retryDelay 在网络重试中的工程取舍?

  • retry 重试次数
  • retryDelay 退避策略
  • 重试与用户体验

retry 控制请求失败后的重试次数(默认 3 次),retryDelay 控制重试间隔(默认指数退避)。工程取舍:重试能容忍瞬时网络错误,但过多重试浪费资源、延迟错误反馈;应以退避策略(指数退避+抖动)避免集中重试打爆服务器。对不可恢复错误(如 4xx)可关闭重试或自定义条件。需在"可靠性"与"响应速度"间平衡,并区分网络错误与业务错误。

retry 提升可靠性,retryDelay 的退避策略避免风暴。合理配置(如指数退避、区分错误类型)是重试的关键,避免盲目重试。

#

31. TanStack Query 的 queryClient 单例在多模块共享的工程实践

请解释 TanStack Query 的 queryClient 单例在多模块共享中的工程实践?

  • queryClient 单例的创建与共享
  • QueryClientProvider 注入
  • 跨模块数据访问

queryClient 通常作为模块级单例创建,通过 QueryClientProvider 注入到组件树,各模块通过 useQuery/useQueryClient 访问。单例让跨模块共享缓存数据、统一配置(默认 staleTime/retry)成为可能。工程实践:在应用入口创建 queryClient 并配置默认值,通过 getQueryData/setQueryData 命令式访问共享缓存。注意 SSR 下需请求级实例,客户端用单例。

queryClient 单例是"共享缓存与配置"的载体。统一配置保证一致性,命令式 API 支持跨模块数据访问,是服务端状态管理的核心基础设施。

#

32. TanStack Query 的 suspense: true 在 React 19 Suspense 的工程协作

请解释 TanStack Query 的 suspense: true 在 React 19 Suspense 中的工程协作?

  • suspense: true 启用 Suspense 模式
  • 与 React 19 Suspense 集成
  • 错误边界配合

设置 suspense: true 或全局 useSuspenseQuery 后,查询在 pending 时抛出 promise 触发最近的 Suspense 边界,显示 fallback。与 React 19 的 Suspense 集成:可把数据获取编排进 Suspense,配合流式渲染与错误边界。工程协作要点:设置合适的 Suspense fallback 层级与 ErrorBoundary,避免错误冒泡导致白屏;Suspense 模式下查询状态由框架管理,无需手动处理 loading。

suspense: true 把数据加载变成"声明式"的 Suspense 暂停。React 19 升华了 Suspense 能力,配合错误边界与流式渲染,实现优雅的加载与错误体验。

#

33. TanStack Query 的 initialData 在 SSR 与客户端注水的工程应用

请解释 TanStack Query 的 initialData 在 SSR 与客户端注水中的工程应用?

  • initialData 提供初始数据
  • SSR 预取数据注入
  • 避免首屏请求

initialData 为查询提供初始数据,首屏直接使用而无需请求。SSR 场景中,服务端预取数据后通过 initialData 传给客户端,客户端 hydrate 时直接使用,避免重复请求与 loading。与 staleTime 结合可让 initialData 维持一定新鲜度。工程价值:服务端数据无缝注入客户端,减少首屏请求,保证 SSR 与客户端数据一致。

initialData 是"初始数据填充"。SSR 中它承接服务端预取结果,客户端当次渲染直接使用,避免闪屏与重复请求。

#

34. TanStack Query 的 structuralSharing 在大数据响应的工程优化

请解释 TanStack Query 的 structuralSharing 在大数据响应中的工程优化?

  • structuralSharing 的结构共享
  • 减少引用变化与重渲染
  • 大响应优化

structuralSharing 在数据更新时尽量复用未变化的部分引用,只替换变化的节点,从而减少新对象引用,让依赖缓存数据的组件因引用稳定而减少重渲染。对大数据响应尤其有价值:数据整体变化不大时,通过结构共享避免组件树大规模重渲染。工程优化:默认开启,对不可变数据或不需要共享的场景可关闭以节省比较开销。

structuralSharing 是"引用复用"优化。它减少因数据刷新产生的引用变化,从而提升渲染性能,是大数据响应下的关键优化。