State Modeling in React with XState
Table of Contents
IntroductionDavid Khourshid introduces the course and demonstrates how to install and run the exercises in the GitHub repository.
Component State in ReactDavid describes software modeling as knowing how an application will behave at any given time. A React component can model its state with the useState hook, however, the logic can get complex when there are multiple state values to manage.
Diagramming a State MachineDavid uses an online tool Excalidraw to diagram the state machine for the toggle component. There are three states: inactive, pending, and active. The events that trigger the stage changes are the toggle event and a success event.
Refactoring with useReducerDavid recommends refactoring any useState hooks to the useReducer hook as a first step for incorporating a state machine. The state logic is centralized within the reducer making it easier to understand and share across components.
Using a Machine ObjectDavid refactors the switch statement to use a machine object. The flow of the component's state changes are configured in the machine object and can be visualized with an tool like the XState Visualizer.
State Machine ExerciseStudents are instructed to create a state machine from scratch using the useReducer hook.
State Machine SolutionDavid live codes the solution to the State Machine exercise.
Refactoring to XState useMachineDavid describes XState as a state machine and state chart library. The state machine object is used within XState by passing it to the createMachine method.
Using XState ExerciseStudents are instructed to use the state machine within XState and XState React.
Using XState SolutionDavid live codes the solution to the Using XState exercise. The XState Inspect tool is also covered in this segment.
Extended StateDavid explains that extended state properties are state properties without finite values. They are stored in a context object within the state machine.
Context ExerciseStudents are instructed to use context property to hold the extended state and the assign method to update context property in an action.
Context SolutionDavid live codes the solution to the Context exercise.
Parameterizing ActionsDavid demonstrates how actions can be parameterized for more reusability. Custom parameters are passed to the useMachine hook which overrides the default parameters in the machine.
Parameterizing Actions ExerciseStudents are instructed to move the actions created with the assign() method to parameterized actions.
Parameterizing Actions SolutionDavid live codes the solution to the Parameterizing Actions exercise.
Integrating 3rd Party LibrariesDavid demonstrates how to use XState events with 3rd party libraries in React.
Guarded TransitionsDavid explains how guarded transitions prevent state transitions if a condition is not met. The condition is a function which returns a boolean indicating if the transition should run.
Guarded Transitions ExerciseStudents are instructed to use guarded transitions to model what happens when the timer expires.
Guarded Transitions SolutionDavid live codes the solution to the Guarded Transitions exercise.
Eventless TransitionsDavid explains that eventless transitions are always taken when the state machine is first entered. They are defined using the "always" property of the state node and contain a conditional guard which must evaluate to true in order to run.
Eventless Transitions ExerciseStudents are instructed to use eventless transitions to detect when the timer expires and simplify the guard logic.
Eventless Transitions SolutionDavid live codes the solution to the Eventless Transitions exercise.
Shared States with useServiceDavid uses the useService hook to subscribe to changes in the local time service. The updated time will then be sent to the ForeignClock component's state machine to keep it up-to-date with the Clock component.
Hierarchical StatesDavid explains that hierarchical states are states nested inside a parent state. This creates a composite state where events can propagate from the sub-state and be handled in the parent state.
Hierarchical States ExerciseStudents are instructed to use hierarchical states to add overtime logic, and use forbidden transitions to adjust the behavior of the nested states.
Hierarchical States SolutionDavid live codes the solution to the Hierarchical States exercise. This segment also demonstrates how to use final states to transition a parent state.
Invoking ActorsDavid invokes a promise and a callback to demonstrate how to communicate between actors within a state machine. Promises use onDone and onError transitions based on their result. Callbacks return data after their execution.
Invoking Actors ExerciseStudents are instructed to move the interval logic from the useEffect hook directly into the state machine.
Invoking Actors SolutionDavid live codes the solution to the Invoking Actors exercise.
Spawning ActorsDavid refactors the alarm functionality into a separate component or actor, and creates a state machine for the parent application. After an alarm actor is spawned, its local state is private unless the state is shared with another actor or the parent application by sending an event.
Spawning Actors ExerciseStudents are instructed to distribute the state with actors.
Spawning Actors SolutionDavid live codes the solution to the Spawning Actors exercise.
Model-Based TestingDavid adds model-based testing to the timer application. This approach describes the behavior of the application as a state machine allowing the tests to be written based on how the user will interact with the application.