状态组织
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
Redux 常见问题:状态组织
是否必须将所有状态放入 Redux?应该使用 React 的 useState 或 useReducer 吗?
这个问题没有"标准答案"。部分用户倾向于将所有数据存入 Redux,以始终保持应用状态的完全可序列化和可控性;另一些用户则偏好将非关键或 UI 状态(如"下拉菜单当前是否展开")保留在组件内部状态中。
使用组件本地状态完全可行。作为开发者,_您_需要自主判断应用包含哪些状态类型,以及每种状态应存放在何处。找到适合您的平衡点并遵循即可。
以下经验法则可帮助判断哪些数据应放入 Redux:
-
应用其他部分是否关注此数据?
-
是否需要基于此原始数据派生出衍生数据?
-
相同数据是否驱动多个组件?
-
能否回溯到特定时间点的状态是否有价值(如时间旅行调试)?
-
是否需要缓存数据(即当数据已存在时直接复用而非重新请求)?
-
热重载 UI 组件时(可能丢失内部状态)是否需要保持数据一致性?
扩展阅读
文章
讨论
能否在 store 状态中存储函数、Promise 或其他不可序列化的数据?
强烈建议仅将普通可序列化对象、数组和原始值存入 store。_技术上_确实可以存储不可序列化项,但这会破坏状态持久化/水合能力,并影响时间旅行调试功能。
如果您能接受持久化和时间旅行调试等功能可能无法按预期工作,那么完全可以在 Redux store 中存储不可序列化项。最终这是_您_的应用,实现方式由您决定。如同 Redux 的许多其他特性,请务必理解其中的权衡取舍。
扩展阅读
讨论
如何组织状态中的嵌套或重复数据?
具有 ID、嵌套或关联关系的数据通常应以“规范化”方式存储:每个对象应仅存储一次,并通过 ID 进行索引,其他引用该对象的实体只需存储其 ID 而非整个对象的副本。可将存储的某些部分视为数据库,其中每种类型的项目都有独立的“表”。normalizr 和 redux-orm 等库能为规范化数据管理提供帮助和抽象层。
扩展阅读
文档
文章
讨论
是否应将表单状态或其他 UI 状态放入存储?
决定哪些状态应放入 Redux 存储的经验法则同样适用于此问题。
根据这些经验法则,多数表单状态无需放入 Redux,因为它们通常不会在组件间共享。但这个决定始终取决于具体场景。若您正在编辑存储中的原始数据,或需要在其他组件中反映编辑中的值,则可将表单状态保留在 Redux 中。反之,将表单状态保持在组件本地,仅在用户完成表单时派发动作更新存储可能更简单。
因此大多数情况下您可能也不需要基于 Redux 的表单管理库。我们建议按以下顺序尝试这些方法:
-
即使数据来自 Redux store,也应先手动编写表单逻辑。这很可能已能满足需求。(关于此主题的优秀指导,请参阅 Gosha Arinich 的 React 表单处理文章)
-
若认为"手动"编写表单过于困难,可尝试基于 React 的表单库如 Formik 或 React-Final-Form
-
若确定其他方案无法满足需求而 必须 使用基于 Redux 的表单库,则可考虑 Redux-Form 和 React-Redux-Form
在 Redux 中存储表单状态时,需仔细考量性能特性:每次文本输入按键都分发 action 通常并不高效,建议研究 分发前缓冲按键事件保持本地变更的方法。始终应分析应用的整体性能需求。
其他 UI 状态也遵循相同原则。典型示例是跟踪 isDropdownOpen 标志——多数情况下应用其他部分不关心此状态,应保留在组件内部。但根据应用场景,使用 Redux 管理对话框等弹出窗口、标签页、可展开面板等可能是合理选择。
更多信息
文章