跳至主要内容

Redux 常见问题解答:组织状态

目录

组织状态

我必须将所有状态放入 Redux 吗?我应该使用 React 的 useStateuseReducer 吗?

对此没有“正确”的答案。一些用户更喜欢将所有数据都保存在 Redux 中,以始终维护应用程序的完全可序列化和受控版本。其他人更喜欢将非关键或 UI 状态(例如“此下拉菜单当前是否打开”)保存在组件的内部状态中。

使用本地组件状态是可以的。作为开发人员,有责任确定构成应用程序的哪些状态,以及每个状态应该放在哪里。找到适合您的平衡,并坚持下去。

一些关于确定哪些数据应该放入 Redux 的常见经验法则

  • 应用程序的其他部分是否关心这些数据?
  • 您是否需要能够基于这些原始数据创建进一步的派生数据?
  • 相同的数据是否用于驱动多个组件?
  • 您是否认为能够将此状态恢复到某个时间点(即,时间旅行调试)对您有价值?
  • 您是否希望缓存数据(即,如果数据已存在,则使用状态中的数据,而不是重新请求它)?
  • 您是否希望在热重载 UI 组件时保持此数据一致(这可能会在交换时丢失其内部状态)?

更多信息

文章

讨论

我可以在我的存储状态中放入函数、Promise 或其他不可序列化项吗?

强烈建议您只将纯可序列化对象、数组和基本类型放入您的存储中。从技术上讲,可以将不可序列化项插入存储中,但这样做可能会破坏持久化和重新水合存储内容的能力,以及干扰时间旅行调试。

如果您不介意诸如持久化和时间旅行调试之类的功能可能无法按预期工作,那么您完全可以将不可序列化项放入您的 Redux 存储中。最终,这是您的应用程序,如何实现它取决于您。与 Redux 的许多其他方面一样,请确保您了解所涉及的权衡。

更多信息

讨论

如何在状态中组织嵌套或重复数据?

具有 ID、嵌套或关系的数据通常应以“规范化”的方式存储:每个对象应存储一次,并按 ID 键入,其他引用它的对象应仅存储 ID,而不是整个对象的副本。将存储的某些部分视为数据库,每个项目类型都有单独的“表”可能会有所帮助。诸如 normalizrredux-orm 之类的库可以提供管理规范化数据的帮助和抽象。

更多信息

文档

文章

讨论

我应该将表单状态或其他 UI 状态放入我的 Store 吗?

决定什么应该放在 Redux Store 中的相同经验法则也适用于这个问题。

根据这些经验法则,大多数表单状态不需要放入 Redux,因为它可能不会在组件之间共享。但是,这个决定始终取决于你和你的应用程序。你可能选择将一些表单状态保留在 Redux 中,因为你正在编辑最初来自 Store 的数据,或者因为你需要在应用程序中其他组件中看到正在进行的值。另一方面,将表单状态保留在组件本地,并且只在用户完成表单后才分派一个 action 将数据放入 Store,可能会更简单。

基于此,在大多数情况下,你可能也不需要基于 Redux 的表单管理库。我们建议按照以下顺序尝试这些方法

  • 即使数据来自 Redux Store,也从手动编写表单逻辑开始。这很可能是你所需要的全部。(参见Gosha Arinich 关于在 React 中使用表单的帖子,以获取一些关于此方面的优秀指导。)
  • 如果你决定“手动”编写表单太难,请尝试使用基于 React 的表单库,例如FormikReact-Final-Form
  • 如果你绝对确定你必须使用基于 Redux 的表单库,因为其他方法不足够,那么你可能最终需要查看Redux-FormReact-Redux-Form

如果你将表单状态保留在 Redux 中,你应该花一些时间考虑性能特征。在文本输入的每次按键时分派一个 action 可能不值得,你可能需要查看缓冲按键以在分派之前将更改保留在本地的方法。与往常一样,花一些时间分析你自己的应用程序的整体性能需求。

其他类型的 UI 状态也遵循这些经验法则。经典的例子是跟踪一个 isDropdownOpen 标志。在大多数情况下,应用程序的其他部分并不关心这个标志,因此在大多数情况下它应该保留在组件状态中。但是,根据您的应用程序,使用 Redux 来 管理对话框和其他弹出窗口、选项卡、展开面板等可能是合理的。

更多信息

文章