Table of Contents
IntroductionDavid Khourshid gives an overview of the course structure, mentions the main topics the course covers, and shares the course repository with the students.
The Problem with Adding FeaturesDavid explores the practice of writing bottom-up code, which leads to jumping straight into the code instead of properly modeling an application. Bottom-up code is difficult to test and the introduction of bugs is more common.
The Case for StatechartsDavid explains that the solutions to problems introduced by writing bottom-up code are the use of state machines and statecharts because they allow the developer to follow the application's logic, and visualize the states and the various transitions between the states.
Finite State MachinesDavid explains that each application data flow can be represented by a directed graph, describes the different types of nodes in a directed graph, and demonstrates that finite state machines are directed graphs. Finite states, events, and transitions are also discussed in this section.
Vanilla JS State Machine
Create a State MachineDavid recommends using objects when creating a state machine and switching states, live codes a transition object, and explains how to use an event to transition from a current state to the next state.
Create a State Machine ExerciseStudents are instructed to create a state machine first using a switch statement, then using objects, and toggle between the inactive and active state in both implementations.
Create a State Machine SolutionDavid live codes the solution to the create a state machine exercise.
Modeling StatesDavid explains that, in order to model states, the steps are to choose the states to add to the model, determine which external events will influence the state, determine how to interpret various state machines, and understand what the life cycle of an interpreter is.
Getting Started with XStateDavid explains that XState simplifies a lot of the work needed to model states, demonstrates how to install XState, and demonstrates how to use and import XState.
Transitions, State & Event ObjectsDavid demonstrates what steps to follow to transition from one state to another, and defines and live codes an event.
Interpreting Machines & Creating a ServiceDavid refactors the code created in the previous sections, builds a service, and explains that a service is a run instance of a state machine. If a state machine is a blueprint, a service is one instance of the blueprint.
Visualizing State MachinesDavid explains that one of the advantages of XState is to be able to visualize the machine, and explores the service machine through the XState visualizer.
Refactoring with XState ExerciseStudents are instructed to refactor the code from the state machine execise in section 2 using XState.
Refactoring with XState SolutionDavid live codes the solution to the refactoring with XState exercise.
Interpreter ExerciseStudents are instructed to create an interpreter, to create a service using interpret, and to set the data attribute to either active or inactive. Interpret creates a new interpreter instance for the given machine.
Interpreter SolutionDavid live codes the solution to the interpreter exercise.
Actions in XStateDavid explains that an action in a state machine is a side effect, adds that there are three types of actions, demonstrates which action is triggered each time there is a change of state, and uses the XState visualizer to generate an image of how actions are executed.
XState Actions ExerciseStudents are instructed to build an action with XState that sets the data-point attribute of the element with the box ID to wherever it was clicked on the mousedown event. The goal of the exercise is to determine at what point the mouse is clicked.
XState Actions SolutionDavid live codes the solution to the XState actions exercise.
Statecharts & Assignment ActionsDavid gives a brief history of statecharts, explains that statecharts are diagrams with depth but still close enough to state machines that they can be transformed into each other, and explains the difference between an extended state and a finite state.
Assignment Action ExerciseStudents are instructed to use context to update the extended state of the drag/drop state machine.
Assignment Action SolutionDavid live codes the solution to the assignment action exercise.
Guarded TransitionsDavid explains that guarded transitions are transitions that have a conditional guard called cond that determines if a transition is allowed. If the guard returns a falsey response, no actions are executed and no transactions are taken.
Guarded Transitions ExerciseStudents are instructed to use a guarded transition to prevent the box element from being dragged more than 5 times which gives more control over possible inputs. This exercise introduces students to building transitions.
Guarded Transitions SolutionDavid live codes the solution to the guarded transitions exercise.
Transient TransitionsDavid explains that transient transitions are different than regular transitions because they happen on null events. They are transitions that are automatically taken when entering a state.
Transient Transitions ExerciseStudents are instructed to only allow authorized users to be able to drag the box element by using transient transitions.
Transient Transitions SolutionDavid live codes the solution to the transient transitions exercise.
Delayed Transition ExerciseStudents are instructed to build functionality ensuring that the box element cannot be dragged for more than two seconds, after David explains that transitions happen in zero time, are never asynchronous, and that delayed transitions have a delay action.
Delayed Transition SolutionDavid live codes the solution to the delayed transition exercise, and demonstrates how to build an add-on for a usecase.
Hierarchical, History & Parallel States
Nested or Hierarchical StatesDavid explains that states that have common behaviors can be nested together within a visible state. Hierarchical states are equivalent to nested states.
Nested States ExerciseStudents are instructed to write code that will allow the box element to only move on the X-axis when the shift key is pressed.
Nested States SolutionDavid live codes the solution to the nested states exercise.
History StatesDavid explains that a history state allows going back to the last visited child of a parent state. History states are mostly useful when working with hierarchical and parallel states.
History States ExerciseStudents are instructed to create a state machine that shows and hides a display, and to use a history state to be able to visit the most recent mode or child state of the visible parent state.
History States SolutionDavid live codes the solution to the history states exercise.
Parallel StatesDavid explains that parallel states can seem paradoxical to state machines because they allow being in two different states at the same time. However, the correct way of thinking about parallel states is to imagine a combination of states. Another word for parallel states is orthogonal states.
Parallel States ExerciseStudents are instructed to build orthogonal states where light and dark mode happen at the same time as bright and dim mode.
Parallel States SolutionDavid live codes the solution to the parallel states exercise and answers to questions from the audience about how to combine both parallel and history states.
The Actor ModelDavid explains that the actor model is an entity that can send a message to another actor, can create new actors, or can change its behavior as a response to a message. An actor is embodied by using invoke, and can invoke a promise, a callback, an observable, or a machine.
Actor Model ExerciseStudents are instructed to use the invoke property to invoke a promise that eventually resolves or rejects with a value, and to then transition to the appropriate states.
Actor Model SolutionDavid live codes the solution to the actor model exercise, and answers questions from the audience about queuing messages.
Invoking ServicesDavid demonstrates how to invoke observables and callbacks by refactoring the code from the actor model exercise.
Using XState with ReactDavid demonstrates how to refactor React code using XState by using specific hooks and reducers provided by React and linking XState to the framework.
Using XState with RxJSDavid explains that RxJS and XState work well together by using an interpreted machine or service one can subscribe to that interprets XState into RxJS.
XState React Hooks & Vue HooksDavid explains that, similar to React, Vue has specific hooks that allow the use of XState with the framework. Vue provides the useMachine hook, which needs to be added to an object named setup that returns the two reactive values state and send.
XState FSM, Testing XState & immerDavid explains that XState with finite state machine Finite State Machine or FSM has no hierarchy, which allows the package to be small, introduces testing with XState, and recommends the use of the immer library. The immer library allows developers to update a state by mutating a proxy of the state.
Spawning vs Invoking ActorsDavid explains that spawning is creating a finite number of new actors that are available for an infinite amount of time until the machine is stopped, and invoking requires a single actor or a small amount of actors and is linked to a specific state and therefore has a specific life cycle.
Redux vs XStateDavid explains that Redux embraces the idea that there is one atomic global state, states that using the actor model is best practice because it separates children and parent states more effectively. The actor model has a higher learning curve.
React and XState Q&ADavid answers questions from the audience about using a service with React and XState, and about statecharts and its modeling of complexity.