Redux 和状态机(例如 xstate)之间的实际区别是什么?

我正在研究一个中等复杂度的前端应用程序。目前它是用纯 javascript 编写的,它有许多不同的基于事件的消息,连接着这个应用程序的几个主要部分。

我们决定,在进一步重构的范围内,需要为这个应用程序实现某种状态容器。以前,我有一些经验与 redux 和 ngrx 存储(实际上遵循相同的原则)。

Redux 是我们的一个选项,但是一个开发人员提议使用基于状态机的库,特别是 Xstate 图书馆

我从来没有使用过 xstate,所以我觉得它很有趣,并开始阅读文档和查看不同的示例。看起来很有前途,很强大,但在某些时候,我明白了,我没有看到任何重大差异之间的它和归还。

我花了几个小时试图找到一个答案,或任何其他信息比较 xstate 和 redux。我没有找到任何明确的信息,除了一些文章,比如 “ get from redux to a state machine”,或者关于使用 redux 和 xstate 一起的库的链接(非常奇怪)。

如果有人能够描述这种差异或者告诉我什么时候开发人员应该选择 xstate-欢迎您。

31718 次浏览

我创建了 XState,但我不会告诉您是否使用其中一个; 这取决于您的团队。相反,我将试图强调一些关键的差异。

复制 XState
本质上是一个状态容器,其中事件(在 Redux 中称为 行动)被发送到一个更新状态的减速器 也是一个状态容器,但将有限状态(如 "loading""success")与“无限状态”或上下文(如 items: [...])分开
并不规定你如何定义你的减少器-它们是普通的函数,返回给定当前状态和事件(操作)的下一个状态 A“ reduce with rules”——定义由于事件而在有限状态之间进行的合法转换,以及在转换中应该执行哪些操作(或者在进入/退出状态时)
没有是否有一个内置的方式来处理副作用; 有许多社区选择,如 redux-thunk,redux-saga 等。 使动作(副作用)声明和显式-它们是在每个转换(当前状态 + 事件)中返回的 State对象的一部分
目前还没有办法可视化状态之间的转换,因为它不能区分有限状态和无限状态 有一个可视化工具: https://statecharts.github.io/xstate-viz,这是可行的,由于声明性质
在 reducers 中表示的隐式逻辑/行为不能以声明方式序列化(例如,在 JSON 中) 表示逻辑/行为的机器定义可以序列化为 JSON,并从 JSON 中读取; 这使得行为非常可移植,可由外部工具进行配置
不是严格意义上的状态机 严格遵守 W3C SCXML 规范: https://www.w3.org/TR/scxml/
依赖于开发人员手动防止不可能的状态 使用状态图自然地定义处理事件的边界,这可以防止不可能的状态,并且可以静态分析
鼓励使用单一的“全球”原子存储 鼓励使用类似于 Actor 模型的方法,其中可以有许多相互通信的分层状态图/“服务”实例

本周我会在文件中加入更多的关键差异。

状态机 不会告诉(强制)您具有单向数据流。它与数据流无关。它更多的是关于 约束状态变化和关于 状态转换。因此,通常只有应用程序的某些部分是用状态机设计的,只有在需要 限制/禁止某些状态更改并且在转换中是 感兴趣的情况下才需要这样做。

注意,对于状态机,如果出于某种原因(外部 API 依赖等)。.),有机会,应用程序可能会被锁定在一个状态,它不能转换到另一个状态,因为约束,你必须解决它。

但是 如果您只对最后一个应用程序状态本身感兴趣,而不是 状态转换,并且状态约束并不重要,那么您最好不要使用状态机,而是直接更新状态本身(您仍然可以通过 Action 类包装 Singleton 类更新中的状态)。


另一方面,复制单向体系结构框架。单向体系结构强制您拥有单向的数据流。在 Redux 中,它以 User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View开头。与状态机一样,您可以在 Redux 中使用 Middleware 触发副作用。如果需要,可以约束/禁止状态转换。复制力量单向数据流,纯洁!减速器函数,不变状态对象,单个可观察的应用程序状态。

以下是我的一些观点。

  • UI 状态和业务/后端状态在 redux 中耦合在一起。因此,对 ui 或业务状态的每次更新都会在 redux 存储中创建一个数据更新。
  • Xstate 解耦 UI 状态和后端状态。
  • 在 redux 中,所有节点都存在于一个根节点中。
  • 应用程序只能在已定义的状态之间转换。因此,任何错误或错误都可以在机器本身修复。
  • 在 Xstate,内部状态由机器自己管理。
  • 渲染主动保持尽可能多的状态悬挂到机器,如果我们需要,我们可以切换渲染框架相对容易(例如从反应到价值)。
  • 上下文提供具体的类来向外部世界呈现单个接口。