news 2026/8/22 14:43:43

Normy乐观更新实战:用optimisticData与rollbackData实现UI即时响应和自动回滚

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Normy乐观更新实战:用optimisticData与rollbackData实现UI即时响应和自动回滚

Normy乐观更新实战:用optimisticData与rollbackData实现UI即时响应和自动回滚

【免费下载链接】normyAutomatic normalization and data updates for data fetching libraries (react-query, vue-query, trpc, swr, rtk-query and more)项目地址: https://gitcode.com/gh_mirrors/no/normy

Normy 是一个面向数据获取库(react-query、swr、rtk-query、trpc 等)的数据自动归一化库。本文聚焦它的实战利器——乐观更新(Optimistic Update):通过optimisticDatarollbackData两个选项,让 UI 在请求发出瞬间立即响应,失败时又自动回滚到原数据,全程无需手写缓存更新代码。

为什么需要乐观更新?

想象一个"改书名"的按钮:

  • 普通更新:用户点击 → 等待服务器响应 → UI 才变化。网络慢时体验生硬;
  • 乐观更新:用户点击 → UI立刻变成新值 → 后台请求成功则维持,失败则回滚。

手动实现乐观更新很繁琐:你要手动mutate每一个包含该数据的查询,还要在失败时记得把每个查询都还原。查询一多,代码又长又容易漏。这正是 Normy 解决的痛点。

原理:一次乐观数据,更新所有相关查询 ⚡

Normy 会把你应用里的查询数据按id自动归一化存储。当一次变更发生,它只需知道哪个 id 的哪个字段变了,就能自动找出所有引用了该对象的查询并同步更新。

optimisticData就是"提前告诉 Normy 即将发生的变化":

  1. 请求发出前,Normy 用optimisticData更新归一化数据,所有相关查询的 UI 立即刷新;
  2. 请求成功后,服务端真实响应再走一次标准归一化流程,UI 与服务器保持一致;
  3. 请求失败后,rollbackData生效,UI 自动恢复原状。

SWR 集成:一个完整示例

先安装并挂载 Provider(详见 packages/normy-swr/README.md):

npm install @normy/swr
const updateBookNameMutation = useNormalizedSWRMutation( 'mutation-key', async () => Promise.resolve({ id: '1', name: 'Name updated' }), { // 请求前:UI 立刻显示新名字 optimisticData: { id: '1', name: 'Name updated' }, // 失败时:自动恢复旧名字 rollbackData: { id: '1', name: 'Name' }, }, );

就这么几行,所有包含id: 1这本书的查询(列表页、详情页……)都会瞬间更新。核心实现逻辑在 useNormalizedSWRMutation.ts:请求发起时触发乐观更新,onError时触发回滚。

react-query 集成:放进 onMutate 的 context 🔁

react-query 官方支持在onMutate返回 context,Normy 会订阅 MutationCache 自动读取:

useMutation({ mutationFn: async () => ({ id: '1', name: 'Name 1 Updated' }), onMutate: () => ({ optimisticData: { id: '1', name: 'Name 1 Updated' }, rollbackData: { id: '1', name: 'Name 1' }, }), });

pending 状态触发乐观更新、error 状态触发回滚的监听代码位于 create-query-normalizer.ts,完整文档见 packages/normy-react-query/README.md。

实战技巧清单 💡

  1. rollbackData要存"改之前"的值:从当前查询数据中取出旧值传入,回滚才准确;
  2. 可加normalize: false避免重复工作:如果你确定响应结构与optimisticData一致,可以在 mutation 上设置normalize: false,成功后不再重复归一化一次(两个集成的文档都有示例);
  3. 嵌套对象同样有效optimisticData里的嵌套对象(如author: { id, name })也会按 id 归一化,一次更新联动多处;
  4. 顶层数组仍需手动处理:往列表头部/尾部"插入"或"删除"元素这类结构变化,Normy 无法判断插入位置,仍需手动更新——这与它的定位一致,只自动化"按 id 的内容变更"。

动手体验:跑一个官方示例 🚀

仓库内置了四种集成的可运行示例,其中 SWR 示例演示了带 3 秒延迟的乐观改名 + 回滚:

git clone https://gitcode.com/gh_mirrors/no/normy

关键文件:

  • SWR 乐观更新示例:examples/swr/src/components/app.jsx
  • react-query 乐观更新示例:examples/react-query/src/components/app.jsx
  • tRPC 乐观更新示例:examples/trpc/src/components/app.tsx

小结

选项触发时机作用
optimisticData请求发出瞬间UI 立即呈现"预期结果"
服务端响应请求成功按真实数据自动校正所有查询
rollbackData请求失败自动回滚到原数据

用 Normy,"即时响应 + 自动回滚"从几十个缓存操作的手工活,变成两行配置——这就是数据归一化带来的红利。

【免费下载链接】normyAutomatic normalization and data updates for data fetching libraries (react-query, vue-query, trpc, swr, rtk-query and more)项目地址: https://gitcode.com/gh_mirrors/no/normy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!