乐观更新
Optimistic UI
点下去界面立刻变成成功的样子,请求在后台跑,失败了再退回去。
- 又叫:
- 乐观更新
- 先改后存
- 点了立刻变
- optimistic update
- rollback on failure
- immediate UI
- 展厅
- 交互反馈
- 形态
- 固定舞台
- 播放
- 手动触发
- 关键词
- 需要 JS / 有状态 / 键盘可用 / 可以直接用
参数工作台
复制给 AI
随参数实时更新做一个乐观更新(optimistic UI)的点赞列表:点击后立刻把这一条改成已赞、计数 +1,同时标记 pending,不等接口返回。模拟请求延迟 1200ms,失败概率 30%,失败时按 id 回滚到原状态并在那一条上显示「失败,已撤销」的提示。用 useOptimistic 或本地 state 实现,注意快速连点的竞态。
optimistic UI like button, update state immediately on click and mark pending, no await, simulated latency 1200ms, failure rate 30%, rollback by id on error with an inline error message, handle race conditions (last write wins), useOptimistic, aria-live polite for the error
https://publieople.github.io/design-museum/entry/optimistic-ui/?stage=light
链接带着你调好的参数
什么时候用
- 点赞、收藏、关注这类高频、低风险、可重复的操作
- 发送消息或评论,希望它立刻出现在列表里,而不是等服务器回声
- 网络慢的时候想减少等待感,把结果先摆出来
适用场景:列表 / 按钮 / 表单
推荐取值
- 界面更新延迟
- 0ms(点击即变)
- 失败提示停留
- 2–4s
- 请求超时
- 5–10s
- 回滚过渡
- 200–300ms
别搞混
和「加载中(loading / disabled)」的区别
loading 明确说「正在提交,先等一下」,还会把按钮锁住;乐观更新反过来,先显示结果、把等待藏起来,只在失败时才提示并回滚。
和「本地缓存(local cache)」的区别
乐观更新只改当前这一次的界面状态,刷新就没了;缓存是真正存下来的数据,下次打开还在。
容易踩的坑
- 支付、下单、删除账号这类不能重放的操作不能乐观,必须等服务器确认
- 失败必须回滚并给出提示(toast 或内联错误),只回滚不提示,用户会以为自己成功了
- 快速连点会产生竞态,给请求编号或声明「最后一次为准」,别让旧响应覆盖新状态
- 回滚要按 id 定位那一条,不要按数组下标,否则列表并发更新时会改错行
无障碍降级
回滚的颜色和位移过渡在 prefers-reduced-motion 下取消,状态直接切换,但「已撤销」的文字或图标提示必须保留。
关键词
- optimistic UI
- rollback
- useOptimistic
- race condition
- pending state
- reconcile