React Query 乐观更新
date
Nov 5, 2025
slug
react-query-optimistic-update
status
Published
tags
React Query
summary
让你的应用"先斩后奏"的艺术
type
Post
小伙伴们好!今天咱们聊聊一个让用户觉得你的应用"快如闪电"的黑科技——乐观更新!
开场:等待的痛苦
还记得上次你点击"点赞"按钮,然后等了1秒才看到效果吗?
这就像在餐厅点菜:
- 传统方式:点菜 → 等厨师确认 → 才在菜单上打勾
- 乐观更新:点菜 → 立即打勾 → 厨师说没货再划掉
问题演示:卡顿的复选框
看看这个待办事项应用,每次点击复选框都要等服务器响应:
用户体验:点击 → 等待... → 变化
这感觉就像:
- 按电灯开关,灯要思考1秒才亮
- 按电梯按钮,按钮要请示总部才亮起
太!难!受!了!
初级方案:基于状态的乐观更新
最简单的想法:突变进行中时,显示相反的状态!
工作原理:
- 用户点击 →
isPending = true→ 立即显示相反状态
- 请求成功 → 更新缓存 → UI保持不变(已经是对的)
- 请求失败 →
isPending = false→ 自动恢复原状态
但是...有个大问题!
连续点击多个复选框时:
这就像多米诺骨牌,第一个倒下时把其他的也带倒了!
高级方案:直接更新缓存
既然问题是缓存和UI不同步,那就直接更新缓存!
步骤1:onMutate - 先下手为强
这就像:先在账本上记账,然后再去银行确认。
步骤2:准备回滚 - 留个后路
万一失败了怎么办?我们需要"后悔药"!
步骤3:onError - 吃后悔药
这就像玩游戏:
- 存档(快照)
- 尝试打Boss(乐观更新)
- 失败了?读档重来(回滚)
完整的防弹方案
执行流程图解
成功流程
失败流程
为什么要 cancelQueries?
想象这个场景:
cancelQueries 就是说:"停!用户在操作,其他请求都让路!"封装:懒人福音
乐观更新代码太多?封装一下!
什么时候用乐观更新?
适合场景 ✅
- 点赞/取消点赞
- 勾选复选框
- 切换开关
- 拖拽排序
- 简单的表单编辑
共同点:操作结果可预测
不适合场景 ❌
- 支付操作(必须等确认)
- 删除操作(可能需要二次确认)
- 复杂计算(结果不可预测)
- 权限相关(可能被拒绝)
最佳实践总结
- 简单场景用状态:单个UI元素,用
isPending控制
- 复杂场景更新缓存:多个元素或需要数据一致性
- 永远准备回滚:乐观不代表盲目乐观
- 最后都要同步:
onSettled是你的最后防线
- 取消竞争请求:避免数据竞争
记住:乐观更新就像"先斩后奏"——大部分时候没问题,但要准备好道歉(回滚)的方案!
好的用户体验 = 快速响应 + 数据准确。乐观更新让你两者兼得!