【发布时间】:2018-07-06 14:34:00
【问题描述】:
在继续之前,我想指出这个问题的标题很难表述。如果应该使用更合适的标题,请告诉我,以便我可以更改它并使这个问题对其他人更有用。
好的,关于这个问题……我目前正在做一个 React/Redux 项目。我做出的一个设计决定是几乎完全使用(分层)状态机来管理应用程序状态和 UI,原因有很多(我不会深入研究)。
我利用 Redux 将我的状态树存储在一个名为 store.machine 的子状态中。然后其余的 Redux 子状态负责存储应用程序“数据”。通过这种方式,我将这两个关注点分开了,这样它们就不会越界了。
由此扩展,我还分离了(React)方面的关注点——使用“状态组件”和“UI 组件”。状态组件几乎完全处理状态流,而 UI 组件是那些在屏幕上呈现的组件。
我有三种状态组件:
- Node:这种状态组件处理状态分支。它根据组件的当前状态(一种委托形式)确定应呈现哪个组件。
- 叶子:这种状态组件存在于状态树的叶子上。它的工作只是渲染一个 UI 组件,传递负责更新状态树的必要“调度”回调。
- Container:这种状态组件封装了一个Node和UI组件并排渲染。
在我的情况下,我们只关心 Node 和 Leaf 组件。我遇到的问题是,虽然 UI 组件是基于“叶状态”呈现的,但在某些情况下,“更高级别”状态可能会影响 UI 的呈现方式。
AppState 以Home 状态开始。当用户单击登录按钮时,将调度 to_login 操作。负责管理AppState 的reducer 将收到此操作并将新的当前状态设置为Login。
同样,在用户键入他们的凭据并完成验证后,success 或 failaction 将被调度。同样,这被同一个减速器拾取,然后继续切换到适当的状态:User_Portal 或 Login_Failed。
我们的顶级Node 接收AppState 作为prop,检查当前状态并渲染/委托给子Leaf 组件之一。 p>
Leaf 组件然后渲染具体的 UI 组件,并传递回调以允许它们调度必要的操作(如上所述)来更新状态。虚线表示 'state' 和 'ui' 之间的边界,并且该边界仅在 Leaf 组件处交叉。这使得独立处理 State 和 UI 成为可能,因此是我想要维护的东西。
这就是事情变得棘手的地方。 想象一下,为了论证,我们有一个顶级状态来描述应用程序所使用的语言——比如说English 和French。我们更新的组件结构可能如下所示:
现在我们的 UI 组件必须以正确的语言呈现,即使描述它的状态不是 Leaf。处理 UI 渲染的 Leaf 组件没有父状态的概念,因此没有应用程序所在语言的概念。因此,语言状态不能安全地传递给UI 不破坏模型。要么必须移除状态/UI 边界线,要么需要将父状态传递给子状态,这两种方法都是糟糕的解决方案。
一种解决方案是为每种语言“复制”AppState 树结构,本质上为每种语言创建一个全新的树结构……就像这样:
这几乎与我上面描述的两个解决方案一样糟糕,并且需要越来越多的组件来管理事情。
更合适的解决方案(至少在处理语言之类的东西时)是避免将其用作“状态”,而是保留一些关于它的“数据”。然后,每个组件都可以查看此数据(currentLanguage 值或以该语言预翻译的消息列表)以正确呈现内容。
这个“语言”问题不是一个很好的例子,因为它可以很容易地构造为“数据”而不是“状态”。但它作为一种方式来证明我的难题。也许一个更好的例子是可以暂停的考试。让我们来看看:
假设考试有两个问题。当处于“暂停”状态时,当前问题被禁用(即无法进行用户交互)。正如您在上面看到的,我们需要为Playing 和Paused 下的每个问题“复制”叶子,以便可以传递正确的状态——由于我之前提到的原因,这是不可取的。
同样,我们可以在某处存储一个描述考试状态的布尔值——UI 组件(Q1 和 Q2)可以轮询的东西。但与“语言”示例不同的是,这个布尔值在很大程度上是一个“状态”,而不是一些“数据”。因此与语言不同的是,这种情况要求将此状态保存在状态树中。
正是这种情况让我难住了。我有哪些解决方案或选项可以让我在利用不包含在叶子中的应用状态信息的同时呈现我的问题?
编辑:以上示例均使用 FSM。在我的应用程序中,我创建了一些更高级的状态机:
- MSM(多状态机):同时处于活动状态的多个状态机的容器
- DSM(动态状态机):在运行时配置的 FSM
- DMSM(动态多状态机):在运行时配置的 MSM
如果这些类型的状态机中的任何一种可以帮助我解决我的问题,请随时告诉我。
非常感谢任何帮助!
这样的结构仍然不允许我将“可暂停”状态信息传递给问题。
【问题讨论】:
-
如果你有多个“独立”状态,而且 MSM 听起来很合理。
-
问题是具有两个状态机的 MSM(1 个 FSM 用于问题,1 个 FSM 用于暂停/播放)仍然不允许暂停/播放状态信息到达问题叶(如果这使得感觉)。两者仍将被视为单独的“分支”,无法合并两组状态信息。
-
still does not allow the pause/play state information to reach the question leaves把它们当作道具传下去? -
@JonasW。请参阅对 OP 的编辑
-
我认为我的问题之一是我只在叶组件上执行 UI 渲染。在遍历树时,我可能需要构建 UI 容器的聚合。
标签: javascript reactjs redux react-redux state-machine