乐观 UI 的竞态条件:只在第五次快速点击时才出现的 Bug
来源:dev.to/shubhradev — 2026-07-21 发布
📋 概述
作者使用 React 的 useOptimistic 为任务列表实现了即时打勾功能,单独点击时完美运行。但当模拟真实用户的快速连续点击(五连击)时,五个重叠请求同时发出,每次翻转同一个布尔值,最终 UI 看起来正确但数据库状态完全不匹配——没有崩溃、没有报错,只是静静地对不上了。修复方案是追踪每个行的待处理状态,在请求完成前禁用对应复选框,让第二次点击无效化而非发出竞态请求。这个修复与表单提交按钮禁止重复点击的原理相同,但作用于逐行级别。
🔑 核心要点
- useOptimistic 让 UI 看起来即时正确,但"看起来正确"和"实际上正确"是两个不同的主张,构成了乐观更新的陷阱。
- 五连击产生了 五个重叠请求,每个翻转同一布尔值,以网络决定的任意顺序抵达,最终数据库状态不可预测。
- 修复方法:用一个 pendingId 状态追踪哪个项有请求在进行中,在请求完成前禁用对应复选框——作用于逐行而非全局锁。
- 核心原则与 禁用提交按钮 防止重复提交相同,但作用范围从表单级缩小到逐行级。
- 在一次评论反馈后,作者进一步认识到:乐观更新本质是一个 两阶段提交问题,需要认真处理中间状态的错误恢复。
💡 金句
Optimistic UI is designed to look right immediately. Looking right and being right are not the same claim.
👍 0👎 0
← 返回 Dev.to 首页