Table of Contents
导言:为什么州管理事务涉及土著反应
国家管理是任何交互 React 本地应用程序的支柱。 您如何存储、更新和共享数据直接影响到您的应用程序的响应性、调试性和维护性。 管理不良的状态会导致UI的停滞、不可预测的错误和缓慢的开发周期。 随着您的应用程序从几个屏幕发展到一个具有实时数据、离线能力和多重用户角色的复杂系统,一个坚实的州管理策略就成为不可谈判的。 文章走过了生产测试的最佳做法 — — 从简单的 使用状态 钩子到像Redux Toolk等全尺寸的库 — — 这样您就可以构建既能发挥效果又容易解释的React 本地应用程序。
了解土著反应状态
React Industrict中状态指的是任何可以随时间变化并影响用户所见的数据。它从一个切换按钮的打开/关闭状态到认证用户的配置或获取产品列表。 广义上状态可以分为两类:
- 本地(组件)状态 — 数据只需要单个组件或小组的兄弟姐妹组件。例如:格式输入、模式可见度、动画进度。
- Global(shared) state — 整个应用程序的许多不相关的组件需要访问的数据。例如:当前用户、购物推车、主题偏好、通知计数。
选择每个状态的存放地点和方式是状态管理的实质。 目标是保持数据流的可预测性,避免不必要的重报,并让状态变化易于追踪。
国家管理的最佳做法
1. 从当地国家开始:[和]
React 的内置钩子是您的第一个而且往往是最好的工具。 [[FLT: 0]] 使用状态 [[FLT: 1] 对于简单的、独立的状态片段来说是理想的,例如一个复选框或文本输入。 当状态逻辑变得更加复杂(多相关值,相互依存更新)时, 切换到[[[FLT: 2]] 使用减速器[] 。 它通过减速器和动作提供了可预测的更新模式, 类似于 Redux , 但范围被缩小到单个组件或小树上。 请不要急于将数据提前拉入全球状态; 您总是可以稍后重置数据。 这样可以保持您的代码库的精度, 组件可以重新使用 。
2. 仅在必要情况下才将国家提升
当两个或两个以上兄弟的组件需要共享同一数据时,平庸的反应方法是“将”该状态提升到最接近的共同祖先。将数据传递给最接近的共同祖先,并将功能更新为道具。这可以避免重复状态,保持单向流动。但是,避免抬高。如果只有两个兄弟的兄弟姐妹共享状态,不要将其一路推向根部;创建一个小的包头组件,它具有共同价值。这个模式尺度自然且容易解释,而不引入外部依赖性。
3. 使用上下文API(用])进行中尺度共享
当道具钻探变得痛苦——通过五层或五层以上——React的上下文 API 提供了更清洁的逃生。创建一个能保存状态对象和调度函数的上下文。将其与 连接到提供者内部,以便集中更新逻辑。这种模式对中等大小的应用程序非常有效:主题、地方、认证状态或特征标记。当上下文值发生变化时,每个用户都要小心。为了减轻这种分解的环境(例如,从中分离)或将上下文值与 相记忆。对于密集的全球状态(如实时种子那样的高频更新),仅背景就会引起性能问题,即需要专门的库。
4. 采用国家大型应用管理图书馆
一旦你的应用达到几十个屏幕,许多同步数据流,复杂的商业规则,一个强大的库就变得至关重要。 在反应原生生态系统中,经过战斗考验的选项是:
- Redux工具包:Redux的官方,有见解的版本. RTK用[]大量切开锅炉板,并内置支持Aync tunks. 它通过immer执行不可变性,简化存储配置,并与Redux DevTools集成用于高级调试. 官方文档.
- Zustand :一个轻量级,首个悬钩状态管理器,且API最小。 您使用 直接从悬钩处创建一个小商店,并访问状态。 Zustand避免了许多Redux的锅炉板,同时仍然提供中间软件(persist, devtools)和出色的性能。 对于想要简单而不会牺牲伸缩性的团队来说,这是理想的。
- MobX-State-Tree(MST):使用可观察状态和隐含的反作用. 定义模型有类型,动作和计算属性. MST自动跟踪依赖性,并只重报消耗已改变值的组件. Great for 开发者喜欢面向对象,模型驱动的方法,想要自动优化.
根据您的团队的熟悉程度和应用程序的具体需要来选择。 对于大多数新项目, [[FLT: 0]] Redux Toolket [[FLT: 1] 或 [[FLT: 2] Zustand 是很好的起点。 避免使用前年的原始Redux锅炉板; 总是使用工具包 。
5. 管理与专用工具同步的国家
服务器牵引数据(API calls, GraphQL, Firebase) 值得它自己处理。 在同一全球商店中, 不要将服务器状态与 UI状态混合。 专用库如 [[FLT: 0]] 唐斯泰克查询(React Query) [[FLT: 1] 和 [[FLT: 2] ] 处理缓存、 脱钩、 背景调整、 标记和乐观的更新。 它们会大幅降低您所写的状态管理代码的数量。 将它们与轻量客户端状态库( Zustand 或本地上下文) 连接起来, 以清理关注事项。 [[FLT: 4] React 查询 docs [FLT: 5] 。
6. 酌情实行顽固的国家
许多 React 本地应用程序需要幸存应用程序重启: 用户偏好、 认证符号、 草稿数据。 坚持状态的关键片段到本地存储。 使用 [[FLT: 0]] 同步程序满足简单的密钥值需求, 但考虑 [[FLT: 2] 反应- 内存- mmkv [[ [FLT: 3]] 在较大的数据集中实现高性能。 库像 [[ [FLT: 4]] redux- persist [[[FLT: 5]] (对于 Redux) 或 [[[FLT: 6]]zustand/midddleware 坚持 [[[FLT: 7] (对于Zustandand) 的无缝同步状态。 选择性地坚持用户会话段真正需要的, 并且不进行适当的加密, 绝对不缓存敏感数据 。
7. 优化性能: 记忆和选择器
过度重交是React Industrial中表现问题的主要原因。
- 经常收到相同道具的组件使用 react.memo[].
- 使用和稳定作为道具传递的物体和函数引用.
- 在使用 Redux 或类似库时,总是从 Reselect 中选择带有记忆选择器的最小数据切片(例如 ) 。这阻止了组件在存储器的不相关部分改变时重交.
- 对于背景重的设置, 将提供者拆分, 这样只让相关的子树重新对更新进行重报 。
用 DevTools 和 Metro 的性能监视器来描述您的应用程序, 以识别热点。 通常, 上下文值上一个缺失的单个 [[FLT: 11]] 可以让整个屏幕减慢 。
8. 测试您的状态逻辑
国家管理逻辑应该孤立地进行测试,而不安装整个组件树。对于 Redux , 使用 [[FLT: 0]] Jest [[FLT: 1] 来为缩小器和动作创建器编写单元测试。 对于 Zustand , 直接通过调用其获取器和设置器来测试商店。 对于上下文 + 使用 降温器, 提取减小器函数, 并测试它为纯函数。 这让你相信状态转换是正常的, 特别是在处理种族条件或 stale 更新等边缘时。 [[FLT: 2] React 本地测试库 [ 可以验证组件是否按照特定状态得出正确的输出 。
附加提示
- 保持状态最小:尽可能从现有状态衍生值(例如,从一个项目阵列计算总价,而不是单独存储).
- 易变性是关键 : 更新状态时总是返回新的对象/阵列。 使用扩展运算符, /], 或像 Immer 这样的库来防止突变错误 。
- 副作用的中件:对于Redux,使用或Redux Saga/Thunk. 对于Zustand,简单函数在商店内部干净地处理副作用.
- 有选择地切换 : 使用反向查询或 SWR 进行服务器状态缓存。 除非您需要下线和稍后同步,否则不要在本地商店中重复服务器数据 。
- 常规重构 : 随着您的应用程序的演进, 重新审视您的状态架构。 当道具钻探变得混乱时, 将本地状态移动到上下文或库中。 删除未使用的状态切片 。
结论
React Industrial 的有效状态管理并不是要遵循一个单一的指定架构,而是要为每种状态选择正确的工具,并保持数据流的可预测性。用 和 简单开始。在应用程序的复杂性需要集中的、可调试的存储时,要使用Redux工具箱或Zustand等库。总是用专用的获取工具将服务器状态与客户状态分开。并且永远不要忘记性能:记忆、明智选择和测试关键路径。
通过将这些最佳做法编织到您的开发工作流程中,您可以构建Resact Industrial应用程序,这些应用程序仍然具有响应性、可维护性以及工作乐趣 — — 即使它们发展到数万行代码。 关键在于将国家视为一流公民,而不是事后思考。