Skip to content

React 项目实践

React 项目如何管理服务端状态和请求缓存?

不要把后端数据简单复制进全局 state,关键是定义新鲜度、身份、失效和错误恢复。

适合阶段:高级前端 / 资深前端核心能力:数据流 · 缓存策略 · 一致性

面试官想考什么

  • 服务端状态和 UI 状态如何区分? 考察状态建模。
  • 如何避免重复请求和请求瀑布? 考察数据获取设计。
  • mutation 后如何更新列表和详情? 考察失效与一致性。
  • 如何处理竞态和过期响应? 考察异步正确性。

一句话回答

text
服务端状态应由查询缓存管理其加载、错误、过期和失效,UI state 只管理交互状态;缓存键、身份和 mutation 失效策略必须明确。

面试回答详解

1. 状态分类

  • UI 状态:弹窗、选中项、输入中内容和局部 loading。
  • 服务端状态:列表、详情、用户资料和远程配置。
  • 派生状态:由已有数据计算出的筛选结果,尽量不要重复存储。
  • 持久化状态:需要跨刷新保留的偏好或草稿。

2. 查询缓存要回答四个问题

text
谁的数据 -> 缓存多久 -> 何时失效 -> 失败如何恢复

缓存键应包含资源、参数、用户或租户维度;请求层可以做去重和取消;页面层通过 Suspense、loading 和 error boundary 表达状态。不要为了“全局共享”把所有服务端数据塞进 Redux。

3. Mutation 和一致性

成功后可以精确更新缓存、乐观更新后回滚,或按标签/资源失效并重新获取。选择取决于更新复杂度、冲突概率和用户对即时反馈的要求。服务端仍是最终事实来源。

4. 生产风险

处理旧响应覆盖新响应、用户退出后的缓存残留、权限变化、跨标签页同步、离线重试、轮询风暴和缓存击穿。监控请求命中率、错误率、延迟和数据新鲜度。

可直接背诵的 30 秒回答

text
我会先把 UI state、服务端状态、派生状态和持久化状态分开。服务端数据交给查询缓存管理请求去重、loading、error、过期和失效,缓存 key 要包含参数、用户或租户维度。mutation 根据场景选择精确更新、乐观更新回滚或失效重取,并通过取消、序列号和监控处理竞态与过期数据。

扩展知识

查询状态机

text
idle -> loading -> success
                 -> error -> retry
success -> refreshing -> success/error

面试官追问链

追问一:为什么不全部用 Redux?

  • 考察点:是否理解服务端状态特殊性。
  • 回答方向:Redux 可以承载领域状态,但查询缓存还需要过期、去重、重试、失效和请求生命周期,专门的查询层通常更合适。

追问二:搜索快速输入时旧结果覆盖新结果怎么办?

  • 考察点:异步竞态处理。
  • 回答方向:取消旧请求、使用请求序号或 query key 校验,只允许当前参数对应的响应写回。

追问三:乐观更新失败怎么办?

  • 考察点:一致性和恢复能力。
  • 回答方向:保存前一版本,失败时回滚并提示;同时重新拉取服务端事实,处理并发修改和幂等。

推荐阅读

基于 MIT 协议开源