点赞按钮点下去先加 1,接口返回 500,数字停在 21,再点一次变成 22,服务端实际还是 20。刷新后掉回 20。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

onMutate: async () => { const prev = qc.getQueryData(['like', id]);
  qc.setQueryData(['like', id], n => n + 1); return { prev }; },
onError: (_e, _v, ctx) => qc.setQueryData(['like', id], ctx.prev)

onMutate 里改了缓存,onError 只弹了个 toast,没有把之前的值写回去。后面每次点击都基于被污染的缓存继续累加,偏差越滚越大。这一点先确认清楚,后面就不用反复试。

「乐观更新回滚」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。

改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

具体做法是,onMutate 里先取消同 key 的在途请求 保存旧值;onError 用保存的旧值恢复缓存;onSettled 统一 invalidate 一次 以服务端为准;故意断网点赞 确认数字能回到原点。

改完照着核一遍,断网点赞后数字先加一再回到 20,恢复网络后与服务端计数一致。

作者 9823189