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

2022-08-30 02:28:58

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

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

Redux对我们来说是一个选项,但是其中一个开发人员建议使用基于状态机的库,特别是xstate库

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

我花了几个小时试图找到答案,或任何其他比较xstate和redux的信息。我没有找到任何明确的信息,除了一些文章,如“从redux到状态机”,或者指向专注于同时使用redux和xstate库的链接(非常奇怪)。

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


答案 1

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

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

本周,我将为文档添加更多关键差异。


答案 2

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

请注意,对于状态机,如果由于某种原因(外部API依赖性等),应用程序可能会锁定在由于约束而无法转换为另一种状态的状态,则必须解决它。

但是,如果你只对上一个应用状态本身感兴趣,而不是状态转换,并且状态约束无关紧要,那么你最好不要使用状态机,而是直接更新状态本身(你仍然可以通过操作类将状态包装在 Singleton 类更新中)。


另一方面,Redux单向架构框架。单向体系结构强制要求单向数据流。在 Redux 中,它以 开头。与状态机一样,您可以在 Redux 中使用中间件触发副作用。如果需要,可以约束/禁止状态转换。不同于状态机,Redux强制单向数据流,纯净!化简器函数、不可变状态对象、单个可观察应用状态。User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View