react中的状态机

by Shawn McKay

肖恩·麦凯(Shawn McKay)

在基于状态图的状态机上使用React的模式 (Patterns for using React with Statechart-based state machines)

Statecharts and state machines offer a promising path for designing and managing complex state in apps. For more on why statecharts rock, see the first article of this series.

状态图和状态机为设计和管理应用程序中的复杂状态提供了一条有希望的途径。 有关状态图为何摇摆的更多信息,请参阅本系列的第一篇文章 。

But if statecharts are such an excellent solution for managing UI & state in Javascript (JS), why isn’t there more momentum behind them?

但是,如果状态图是用Javascript(JS)管理UI和状态的出色解决方案,为什么它们背后没有更多的动力呢?

One of the main reasons statecharts have not grown in popularity within the front-end world is that best practices have yet to be established. It’s not abundantly clear how to use state machines with popular component-based UI libraries such as React, Vue, or Angular.

状态图在前端世界中尚未普及的主要原因之一是尚未建立最佳实践。 尚不清楚如何将状态机与流行的基于组件的UI库(如React,Vue或Angular)一起使用。

While it may be too early to declare best practices for statecharts in JS, we can explore some patterns used by existing state machine integration libraries.

虽然在JS中声明状态图的最佳实践为时过早,但我们可以探索现有状态机集成库所使用的一些模式。

状态图机 (Statechart machine)

Statecharts work both for visual design and as the underlying code for a graph-based state machine.

状态图既可以用于视觉设计,又可以用作基于图的状态机的基础代码。

Bear in mind that we’re in the early days of using statecharts with JS, and it may be worth experimenting with a variety of libraries or even developing your own. That being said, XState is currently leading the pack for statechart machine libraries in JS.

请记住,我们处于将状态图与JS一起使用的初期,可能值得尝试各种库甚至开发自己的库。 话虽这么说, XState目前在JS中领先于Statechart机器库。

The above state machine code can generate a much more readable statechart diagram when passed as JSON to the XState Visualizer.

上面的状态机代码作为JSON传递给XState Visualizer时,可以生成更具可读性的状态图。

You can even work the other way, starting by visually designing and then exporting to an XState configuration using sketch.systems. We don’t have all the pieces in one place yet, but there are no serious technical barriers to an open source solution.

您甚至可以以其他方式工作,从视觉设计开始,然后使用sketch.systems导出到XState配置。 我们还没有将所有内容都放在一个地方,但是开源解决方案没有严重的技术障碍。

Now that we have an idea of what XState does, let’s look at what it doesn’t do.

既然我们已经了解了XState的功能,那么让我们看看它没有做什么。

XState Tagline: “stateless finite state machines and statecharts”.

XState口号:“无状态的有限状态机和状态图”。

So what does it mean for a state machine to be stateless?

那么,状态机是状态的意味着什么呢?

无状态机器 (Stateless machines)

Stateless machines offer an unopinionated blueprint for state management — a kind of “roll your own” solution that doesn’t dictate where or how state in your application is stored.

无状态机器为状态管理提供了一个不受质疑的蓝图 -一种“滚动自己的”解决方案,它不指示应用程序中状态的存储位置或方式。

Much like a presentational component, a stateless machine is made of pure functions, is immutable, and maintains no state. It tracks no past, current, or future — but it can be used to help you calculate each.

无状态机器很像表示组件,是由纯功能组成的,是不变的,并且不保持任何状态。 它不会跟踪过去,现在或将来,但是可以用来帮助您计算每个。

Managing your state can be as easy as storing it in a local state variable.

管理状态就像将其存储在本地状态变量中一样容易。

Stateless machines don’t give you much out of the box. To trigger a transition, we must always pass in the current state node in to find the next. XState can let you know which actions should be fired on each state change, but you’ll have to find a way to manage the actions yourself.

无状态机器无法为您提供很多便利。 要触发转换,我们必须始终传入当前状态节点以查找下一个。 XState可以让您知道在每次状态更改时应触发哪些操作,但是您必须找到一种自行管理操作的方法。

If you’re interested in a more complete solution, consider making your state machine stateful.

如果您对更完整的解决方案感兴趣,请考虑使状态机变为有状态。

状态机 (Stateful machines)

A stateful machine tracks your node position on the state graph and manages the firing of actions. There is no need to pass in the current state on transitions — it tracks your current state node.

有状态机会跟踪您在状态图上的节点位置并管理动作的触发。 过渡时无需传递当前状态-它会跟踪您的当前状态节点。

As a summary, the instance of the stateful machine above:

作为总结,上述有状态机的实例:

  • determines the green state position at “Ringing”确定“ Ring”处的绿色状态位置
  • limits the possible purple’active transition events to CANCEL or SNOOZE

    将可能的“紫色”活动过渡事件限制为“ CANCEL或“ SNOOZE

  • fires the startRing action on entry

    在进入时触发startRing操作

  • fires the stopRing action on leaving the state

    离开状态时触发stopRing动作

Of course, there is more than one way to create a stateful machine. We’re back to the question of where to manage state:

当然,创建状态机的方法不止一种。 我们回到了在哪里管理状态的问题:

  • within the existing component state?在现有组件状态内?
  • in a connected state machine?在连接状态机中?

Let’s explore some design patterns with examples, starting with stateful components.

让我们从状态组件开始,通过示例探索一些设计模式。

有状态的组件 (Stateful components)

A stateful component, as you might imagine, manages state within the component, or within a wrapping higher-order component. In React, this would be as state. Storing state within a UI library ensures that changes won’t be missed and will trigger re-renders.

您可能会想到,有状态组件将管理该组件内或包装的高阶组件内的状态。 在React中,这将是state 。 将状态存储在UI库中可确保不会丢失更改,并会触发重新渲染。

This is the approach of a library called React-Automata that uses a higher-order component initiated by withStatechart.

这是称为React-Automata的库的方法,该库使用由withStatechart发起的高阶组件。

React-Automata offers several patterns for using statecharts with components:

React-Automata提供了几种使用状态图和组件的模式:

  • state from props道具状态
  • conditional rendering from a context上下文中的条件渲染
  • state from actions从行动状态

We’ll go over each pattern and consider the pros and cons.

我们将仔细研究每种模式,并考虑其优缺点。

道具状态 (State from Props)

Passing state directly into components seems like the most obvious solution.

将状态直接传递到组件似乎是最明显的解决方案。

In React-Automata, state can be passed by accessing it on the machineState prop — a reference to the actual state machine.

在React-Automata中,可以通过在machineState道具上访问状态来传递状态,该状态是对实际状态机的引用。

But be wary, this is by no means best practice. In the example above, the integration has coupled the statechart to the component, leading to a poor separation of concerns.

但是要小心, 这绝不是最佳实践 。 在上面的示例中,集成将状态图耦合到了组件,从而导致关注点分离不佳。

Consider that the statechart and components can allow for a clean divide as they solve different problems:

考虑到状态图和组件可以解决不同的问题,因此可以进行清晰的划分:

  • statecharts: when things happen, for example, enter state, actions fired

    状态图: 事情发生时,例如进入状态,触发动作

  • components: how and what happens, for example, the view, user interactions

    组件: 如何以及如何发生,例如视图,用户交互

Alternatively, you could decouple the component from the state machine by conditionally rendering with a default of no render.

或者,您可以通过默认不渲染的有条件渲染来将组件与状态机分离。

Certainly, there must be a more natural way to set up conditional rendering without having to turn all your renders into if/else and switch statements.

当然,必须有一种更自然的方法来设置条件渲染,而不必将所有渲染都转换为if/elseswitch语句。

从上下文进行条件渲染 (Conditional rendering from a context)

State accessed by a context doesn’t need to be passed directly.

上下文访问的状态不需要直接传递。

React-Automata provides a pattern for conditional rendering of child components using React’s context and a <State> component. Note that the value property can match on a string, array of strings, or even a glob-based pattern.

React-Automata提供了一种使用React上下文和<Sta te>组件有条件地渲染子组件的模式。 注意THA t the值属性可以匹配的字符串,字符串数组,或甚至基于水珠图案。

If the state value matches Ringing, the children inside of the State component will render. Otherwise, nothing.

如果状态值匹配Ringing ,则将渲染State组件内的子级。 否则,什么都没有。

State from context can help clarify the number of possible finite state view combinations. As in the case above, it’s clear there are only two possible configurations.

上下文中的状态可以帮助阐明可能的有限状态视图组合的数量。 与上面的情况一样,很明显只有两种可能的配置。

If view configurations start to get out of hand, React-Automata offers a render prop pattern that passes in a boolean based on the value.

如果视图配置开始失控,React-Automata将提供一个渲染道具模式,该模式根据该值传入布尔值。

Similarly, it’s possible to conditional render based on context actions.

同样,有可能根据上下文操作进行条件渲染。

Conditionally rendering based on state or actions maintains a coupling between the statechart and components, but less explicitly through context. How might you give components their isolated state apart from statecharts?

基于状态或动作的有条件渲染可维持状态图和组件之间的耦合,但通过上下文不太明确。 除了状态图,您如何赋予组件孤立的状态?

从行动状态 (State from actions)

It’s possible to use statecharts to update the internal state of a linked component using actions as triggers.

可以使用状态图以动作作为触发器来更新链接组件的内部状态。

React-automata checks the methods on a component and calls the functions if the names match the actions being fired.

React-automata检查组件上的方法,并在名称与要触发的动作匹配时调用函数。

As an example, the onEntry action startRing is fired as the state machine enters Ringing, causing the AlarmClock state to change to ringing. On leaving the Ringing state, stopRing is fired, and ringing is set to false.

例如,当状态机进入Ringing ,会触发onEntry操作startRing ,导致AlarmClock状态更改为ringing 。 退出Ringing状态时,将触发stopRing ,并将ringing设置为false

Note that, although of these methods are called with params, the methods already have access to whatever they need from machineState through props.

请注意,尽管这些方法是用params调用的,但这些方法已经可以通过props从machineState访问所需的machineState

Using internal component state managed through actions leads to a strong decoupling of components from state charts. However, it can also create a degree of clutter or confusion in components. It is not explicitly clear how or when methods will be called without examining the names of actions in the statechart. For this reason, I often call my actions and methods enterX or exitX in order to make it explicitly clear why and where they are being fired.

使用通过操作管理的内部组件状态会导致组件与状态图之间的强烈分离。 但是,它也会在组件中造成一定程度的混乱或混乱。 在不检查状态图中动作名称的情况下,尚不清楚如何或何时调用方法。 因此,我经常将我的操作和方法enterXexitX ,以便清楚地阐明其原因和触发位置。

外部状态机 (External state machines)

Another option worth considering is storing state outside of your UI framework. As with other state management libraries like Redux, components can be connected to an external state machine and updated with “on state change” and “on action” events.

另一个值得考虑的选择是将状态存储在UI框架之外。 与Redux等其他状态管理库一样,组件可以连接到外部状态机,并通过“状态更改”和“动作中”事件进行更新。

As an example, XStateful is a wrapper around XState that handles state, transitions, emitting events, triggering actions, and more.

例如, XStateful是XState的包装,用于处理状态,转换,发出事件,触发动作等。

XStateful works well with a React connector called XStateful-React.

XStateful与一个名为XStateful-React的React连接器很好地配合使用。

XStateful-React has much in common with React-Automata. But there is at least one signficant difference — the state machine instance is not managed within any component.

XStateful-React与React-Automata有很多共同点。 但是,至少有一个显着的区别-状态机实例不在任何组件中进行管理。

So how does external state from reducers work in XStateful?

那么,Reducer的外部状态如何在XStateful中工作?

状态和数据 (State and data)

Applications often require more than just the state node in a state graph— they require data as well. Often this data needs to be synced across components, in a way that can be frustrated if it must be passed from the uppermost shared parent.

应用程序通常不仅需要状态图中的状态节点,还需要数据。 通常,此数据需要跨组件同步,如果必须从最上层共享父级传递数据,可能会感到沮丧。

There are existing popular solutions for syncing data, such as Redux, or my state management wrapper for Redux. Unfortunately, these don’t play well with many state wrappers such as React-Automata due to an open issue with passing refs in React Redux (see this open issue with connect() and React.forwardRef).

有用于同步数据的现有流行解决方案,例如Redux或我的 Redux 状态管理包装器 。 不幸的是,由于在React Redux中传递引用存在开放性问题 (请参见connect()和React.forwardRef的此开放性问题) ,这些方法在许多状态包装器(例如React-Automata)中无法很好地发挥作用。

A complete state solution should manage both state and data.

完整的状态解决方案应同时管理状态和数据。

XStateful offers just such a state and data solution using a state reducer pattern, similar to Redux.

XStateful使用状态减少器模式提供了这种状态和数据解决方案,类似于Redux。

State machine subscribers listen and update changes based on actions emitted from the state machine. Note that XState refers to data as extended state, or extstate.

状态机订户根据状态机发出的操作来侦听和更新更改。 请注意,XState将数据称为扩展状态extstate

This particular Reducer pattern may seem unfamiliar, however, it’s heavily used in projects such as ReasonReact.

这种特殊的Reducer模式可能看起来并不熟悉,但是它在诸如ReasonReact之类的项目中大量使用。

Data can also be accessed in conditional renders on the property cond.

也可以在属性cond条件渲染中访问数据。

Be careful with using state to conditionally render components, as it creates a non-deterministic set of possible states. No longer are you limited to the number of states, but now to the number of state and data combinations. You lose out on deterministic features, discussed later in the testing section.

使用状态来有条件地渲染组件时要小心 ,因为它会创建一组不确定的可能状态。 您不再局限于状态数,而是现在仅限于状态数和数据组合数。 您将失去确定性功能,稍后在测试部分中进行讨论。

This data can be passed into your component using a render prop pattern.

可以使用渲染道具图案将此数据传递到您的组件中。

There is less of a need for state management tools like Redux if data can be stored within a complete state machine tool like XStateful.

如果可以将数据存储在完整的状态机工具(例如XStateful)中,则对Redux之类的状态管理工具的需求就更少了。

测试中 (Testing)

State machines also offer a better path for front-end testing.

状态机还为前端测试提供了更好的途径。

The deterministic nature of state machines creates the possibility of simplified front-end testing.

状态机的确定性性质提供了简化前端测试的可能性。

In React-Automata you can autogenerate snapshot tests using testStatechart, a method that takes the XState configuration and the component.

在React-Automata中,您可以使用testStatechart自动生成快照测试,该方法采用XState配置和组件。

testStatechart runs through the state graph and creates a Jest snapshot test for each possible configuration of the component. It will toggle on and off your various <State />, <Action /> components, leading to a recording of all possible conditional rendering combinations.

testStatechart贯穿状态图,并为组件的每个可能配置创建一个Jest快照测试 。 它将打开和关闭各种<State / >, < Action />组件,从而记录所有可能的条件渲染组合。

开发工具 (Devtools)

Devtools play an active role in what makes a library developer-friendly — debugging can be the hardest or most straightforward part of your job.

Devtools在使库对开发人员友好的过程中扮演着积极的角色-调试可能是您工作中最困难或最直接的部分。

In this respect, React-Automata offers a helpful integration via Redux Devtools. Each connected component becomes a named instance in the devtools, and each transition and action are displayed chronologically as actions are presented in Redux devtools.

在这方面,React-Automata通过Redux Devtools提供了有用的集成。 每个连接的组件在devtools中成为一个命名实例,并且每个动作和动作都按时间顺序显示在Redux devtools中。

XState offers an entirely new set of variables to track. Consider the following example by Erik Mogensen on the kinds of information an XState debugger may track.

XState提供了一组全新的变量来跟踪。 考虑一下Erik Mogensen的以下示例,该示例涉及XState调试器可能跟踪的信息。

This is not to say that state machine devtools need to look like our existing devtools. State machine devtools present an opportunity for a more visual debugging experience.

这并不是说状态机devtools必须看起来像我们现有的devtools。 状态机devtools提供了获得更直观的调试体验的机会。

结论 (Conclusion)

While we’re still in the early days of statecharts in JS, there are enough options available to start developing applications on top of XState. We can learn from these development patterns to both improve available libraries and to create tools to support the enormous potential of visual-based programming.

虽然我们仍处于JS状态图的早期,但是有足够的可用选项来开始在XState之上开发应用程序。 我们可以从这些开发模式中学习,以改进可用的库并创建工具来支持基于视觉的编程的巨大潜力。

Having developed applications with statecharts over the past three months, I’ve personally found these new patterns to be a breath of fresh air. Collaboration has become much more comfortable, as team members can visually grasp the underlying logic of a significant and growing system.

在过去三个月中使用状态图开发了应用程序之后,我个人发现这些新模式令人耳目一新。 由于团队成员可以从视觉上掌握重要且不断发展的系统的基本逻辑,因此协作变得更加舒适。

My hope is that this article will help others find statechart-based development more approachable. If you found it helpful, give a clap and pass it on :)

我希望本文将帮助其他人发现基于状态图的开发更加平易近人。 如果您觉得有用,请鼓掌并继续进行:)

翻译自: https://www.freecodecamp.org/news/patterns-for-using-react-with-statechart-based-state-machines-33e6ab754605/

react中的状态机

react中的状态机_在基于状态图的状态机上使用React的模式相关推荐

  1. react中纯函数_如何在纯React中创建电子邮件芯片

    react中纯函数 by Andreas Remdt 由Andreas Remdt 如何在纯React中创建电子邮件芯片 (How to create email chips in pure Reac ...

  2. react中样式冲突_如何通过React中的样式使您的应用漂亮

    react中样式冲突 by Vinh Le 由Vinh Le 如何通过React中的样式使您的应用漂亮 (How to make your apps pretty with styling in Re ...

  3. 如何在React中从其父组件更改子组件的状态

    by Johny Thomas 约翰尼·托马斯(Johny Thomas) 如何在React中从其父组件更改子组件的状态 (How to change the state of a child com ...

  4. 源码 状态机_阿里中间件seata源码剖析七:saga模式实现

    saga模式是分布式事务中使用比较多的一种模式,他主要应用在长流程的服务,对一个全局事务,如果某个节点抛出了异常,则从这个节点往前依次回滚或补偿事务.今天我们就来看看它的源码实现. 状态机初始化 在之 ...

  5. react中嵌入网页_在网站中添加 React

    根据需要选择性地使用 React. React 从一开始就被设计为逐步采用,并且你可以根据需要选择性地使用 React.可能你只想在现有页面中"局部地添加交互性".使用 React ...

  6. java中逻辑运气_一个基于运气的数据结构,你猜是啥?

    排行榜 懂行的老哥一看这个小标题,就知道我要以排行榜作为切入点,去讲 Redis 的 zset 了. 是的,经典面试题,请实现一个排行榜,大部分情况下就是在考验你知不知道 Redis 的 zset 结 ...

  7. react中使用构建缓存_使用React构建Tesla的电池范围计算器(第1部分)

    react中使用构建缓存 by Matthew Choi 由Matthew Choi 使用React构建Tesla的电池范围计算器(第1部分) (Building Tesla's Battery Ra ...

  8. react中使用构建缓存_完整的React课程:如何使用React构建聊天室应用

    react中使用构建缓存 In this video course, you'll learn React by building a chat room app. 在本视频课程中,您将通过构建聊天室 ...

  9. this指向、数据双向流、传递参数、JSX中循环、React中样式、路由、引入资源的其它方式、create-react-app脚手架、事件处理、获取数据、UI框架推荐、pc桌面应用electronjs

    改变this指向的几种方式: //1.使用箭头函数代替原始函数写法:getState=()=>{}//2.在函数调用时给函数名加bind(this)方法:(bind中第一个参数表示修改this指 ...

最新文章

  1. 2019年中国科创板全面解读报告
  2. 转载一篇开源http服务器(C语言)
  3. 《F4+2团队项目系统设计改进》
  4. python中的pass是空语句一般用作占位语句_1、python基本语法
  5. python多轴图_Python多子图布局与坐标轴科学计算方法,python,及,计数法
  6. JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
  7. 在VMware安装Windows server 2003步骤
  8. 【JY】基于OpenSees和SAP2000静力动力计算案例分析
  9. UE4蓝图API翻译【节点】--- Get All Actors with Tag
  10. 组图:1968年墨西哥城奥运会
  11. 【数据结构课程设计】基于商和余数的快速排序
  12. 最快的Android TreeView出现了!
  13. 代码式动态录入生成个人简历页面html页面前端源码
  14. 微信小程序分析送积分功能如何实现_微信小程序积分商城解决方案(一)
  15. unity游戏开发知识检测
  16. gt; 和 lt; 代表大于号gt; 和小于号lt; 以及其英文的全称
  17. mv移动或重命名文件
  18. java pdf添加透明水印,PDF怎么加透明水印?
  19. sequoia,一个非常通用的数据库集群解决方案
  20. 华为手机升级回退_华为荣耀手机系统回退

热门文章

  1. 不愧是阿里大佬,mysql存储过程写法案例
  2. 安卓开发工程师面试题!春招我借这份PDF的复习思路,不吃透都对不起自己
  3. 海龟绘图小动物_震惊!被塑料绳勒成两半的海龟
  4. 大项目之网上书城(八)——数据库大改添加图书
  5. 【原创】数据库中为什么不推荐使用外键约束
  6. django-celery定时任务以及异步任务and服务器部署并且运行全部过程
  7. MySQL的变量分类总结
  8. (转载)JDOM/XPATH编程指南
  9. [转]DevExpress GridControl 关于使用CardView的一点小结
  10. 小白学jquery Mobile《构建跨平台APP:jQuery Mobile移动应用实战》连载四(场景切换)...