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):通过optimisticData与rollbackData两个选项,让 UI 在请求发出瞬间立即响应,失败时又自动回滚到原数据,全程无需手写缓存更新代码。
为什么需要乐观更新?
想象一个"改书名"的按钮:
- 普通更新:用户点击 → 等待服务器响应 → UI 才变化。网络慢时体验生硬;
- 乐观更新:用户点击 → UI立刻变成新值 → 后台请求成功则维持,失败则回滚。
手动实现乐观更新很繁琐:你要手动mutate每一个包含该数据的查询,还要在失败时记得把每个查询都还原。查询一多,代码又长又容易漏。这正是 Normy 解决的痛点。
原理:一次乐观数据,更新所有相关查询 ⚡
Normy 会把你应用里的查询数据按id自动归一化存储。当一次变更发生,它只需知道哪个 id 的哪个字段变了,就能自动找出所有引用了该对象的查询并同步更新。
optimisticData就是"提前告诉 Normy 即将发生的变化":
- 请求发出前,Normy 用
optimisticData更新归一化数据,所有相关查询的 UI 立即刷新; - 请求成功后,服务端真实响应再走一次标准归一化流程,UI 与服务器保持一致;
- 请求失败后,
rollbackData生效,UI 自动恢复原状。
SWR 集成:一个完整示例
先安装并挂载 Provider(详见 packages/normy-swr/README.md):
npm install @normy/swrconst 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。
实战技巧清单 💡
rollbackData要存"改之前"的值:从当前查询数据中取出旧值传入,回滚才准确;- 可加
normalize: false避免重复工作:如果你确定响应结构与optimisticData一致,可以在 mutation 上设置normalize: false,成功后不再重复归一化一次(两个集成的文档都有示例); - 嵌套对象同样有效:
optimisticData里的嵌套对象(如author: { id, name })也会按 id 归一化,一次更新联动多处; - 顶层数组仍需手动处理:往列表头部/尾部"插入"或"删除"元素这类结构变化,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),仅供参考
