当在大型 React Native 应用中真正需要客户端实体规范化时

发布: (2026年1月9日 GMT+8 20:12)
5 min read
原文: Dev.to

Source: Dev.to

背景

在过去的几年里,我在多个 React Native 项目中工作——不同的产品、不同的团队——时常遇到非常相似的症状。

随着应用的增长,同样的实体开始出现在越来越多的地方:

  • 信息流
  • 详情页
  • 搜索结果
  • 通知
  • 背景更新

每个新功能都会引入一些小而合理的决定:

  • 缓存列表响应
  • 在屏幕聚焦时重新获取
  • 合并局部更新
  • 添加派生选择器
  • 手动在屏幕之间同步数据

单独来看,这些选择都有道理。整体上,它们都在尝试解决同一个根本问题。到某个时点,这已经不再是偶然。

当归一化看似不必要时

长期以来,只要数据:

  • 属于单个屏幕
  • 生命周期短暂
  • 不会在其他地方复用

在这些情况下,把数据紧贴 API 响应保存完全可行,进行归一化只会增加繁琐而收效甚微。

当归一化变得必要时

问题出现在数据不再是屏幕局部的那一刻。Redux ToolkitReact Query 之所以受欢迎是有原因的,但它们的强大恰恰也是它们的宽泛。

我的核心需求要窄得多:在多个屏幕之间共享数据的响应式更新,并保持稳定的身份标识

  • MobX 在这方面表现极佳。

  • 其余的架构随后出现,遵循相当标准的 clean‑code 原则:

    • 归一化以避免实体实例重复
    • 用显式关系取代嵌套 DTO 树
    • 为长期存活的数据设定生命周期边界
    • 使用异步编排避免竞争条件

这些都不是事先规划好的。随着时间推移,代码库的增长更多体现在协同逻辑而非功能本身。

数据生命周期挑战

实体不再只属于单个屏幕。缺乏显式规则会导致:

  • 内存增长且没有明确的驱逐策略
  • 通过遗忘的引用意外保留数据
  • 对“谁拥有”数据产生不确定性

当生命周期成为明确关注点时,随着这些关注点被显式化并可组合,出现了真正的转变:

  • 垃圾回收策略
  • 持久化
  • 异步控制(取消、重试、刷新)
  • 集成边界

把它们视为可插拔层能够澄清职责。

提炼方法

此时,结构已经不再局限于单个项目。将这种方法抽取成一个小库并非最初的目标;它之所以出现,是因为同样的结构在多个项目中反复出现。它仍然是一个实验性质的实现。

如果你感兴趣,我已经把该方法抽取成一个小型开源实验:

https://github.com/nexigenjs/entity-normalizer

未解之问

我认为这里没有唯一正确的答案。我想了解其他人现在是如何处理的:

  • 客户端实体归一化在什么情况下开始对你产生价值?
  • 你如何划分服务器缓存与领域实体的界限?
  • 你如何处理共享客户端数据的生命周期和所有权?
Back to Blog

相关文章

阅读更多 »

NgRx Toolkit v21

NgRx Toolkit v21 NgRx Toolkit 起源于 SignalStore 甚至还未标记为稳定的时期。 在那些早期,社区对各种 f...

React 是如何工作的?

Component 是 React 应用的基础,应用由 Component 组成。Component 只是一个返回 UI 的 JavaScript 函数。javascript function App { return Hello ; } JS...