主题
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 校验,只允许当前参数对应的响应写回。
追问三:乐观更新失败怎么办?
- 考察点:一致性和恢复能力。
- 回答方向:保存前一版本,失败时回滚并提示;同时重新拉取服务端事实,处理并发修改和幂等。