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


85

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

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

Redux是我们的一种选择,但是其中一位开发人员建议使用基于状态机的库,尤其是xstate库

我从未使用过xstate,因此我发现它很有趣,并开始阅读文档并查看不同的示例。看起来很有前途且功能强大,但在某些时候我了解到它与redux之间没有任何明显的区别。

我花了几个小时试图找到答案,或者比较xstate和redux的任何其他信息。我没有找到任何明确的信息,除了像一些文章“从终极版获得一个状态机”,或链接库集中于使用终极版和XSTATE在一起(很奇怪)。

如果有人可以描述差异或告诉我开发人员何时应该选择xstate,欢迎您。


3
官方的文档实际上是说,你应该把你的终极版减速状态机redux.js.org/style-guide/...
Yannic哈曼

我认为您提到的库可能是使用xstate作为效果管理系统(替代了thunk,saga,epic等)
Alfred Young

Answers:


187

我创建了XState,但是我不会告诉您是否要在另一个之上使用它。这取决于您的团队。相反,我将尝试强调一些关键差异。

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

我将在本周向文档添加更多关键区别。


5
最终有人使用FSM和SCXML进行前端开发...您救了我的命,我将学习您的库。由于某些原因,我不喜欢redux(首先,它混淆了事件和操作项),其次,它使用百万个标记来“建模”复杂的状态(冗长和不正确​​)。
卡洛斯·韦尔德

1
@ Mike76 XState与Redux开发工具集成。
David Khourshid

感谢您的提示,我将对此进行研究。
Mike76

1
我现在已经尝试了XState + Redux DevTools。它工作得很好,但是似乎缺少一些功能。例如,XState + Redux DevTools不支持“状态重播”之类的功能,在这些功能中会重播一系列先前的状态。这是由于实施限制吗?
Mike76

20

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

请注意,在状态机的情况下,如果由于某种原因(外部API依赖关系等),应用可能会因为某种限制而被锁定在无法转换为另一状态的状态,则必须解决该问题。

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


另一方面,Redux单向架构框架。单向架构强制您具有单一方向的数据流。在Redux中,它以开始User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View。像状态机一样,您可以在Redux中使用中间件来触发副作用。如果需要,可以约束/禁止状态转换。与状态机不同,Redux强制单向数据流,纯粹!减速器功能,不可变状态对象,单个可观察的应用程序状态。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.