乐观更新后 UI 没回滚,状态怎么处理?
我用 React 做了个点赞功能,点了之后立刻更新 UI(乐观更新),但请求失败时 UI 没变回去,反而卡在“已点赞”状态。是不是哪里没处理好?
我试过在 catch 里手动 revert 状态,但有时候会因为组件卸载导致 setState 报错。下面是我简化后的代码:
<button onClick={handleLike}>
{{ isLiked ? '已点赞' : '点赞' }}
</button>
// handleLike 伪逻辑:
// setLiked(true)
// api.like().catch(() => setLiked(false))
最直接的解决方案是用一个标记来控制是否更新状态:
这样组件卸载后就不会再执行 setState 了。
不过更推荐的做法是用现成的库,比如 React Query 或者 SWR,它们内置了乐观更新和自动回滚的机制,帮你省掉很多这种边界情况的处理:
如果你不想引入额外依赖,第一种 ref 方案就够用了。记得在清理函数里把 isMounted 设为 false,这样就能安全处理组件卸载的情况。
1. 用一个ref记录组件是否已卸载
2. catch里先检查这个ref再setState
改后的代码大概这样:
或者更简单的方案是用AbortController取消请求,不过要改api调用方式。建议优先用上面这个方案,我们项目里基本都这么处理,稳得很。