Join egghead, unlock knowledge.

Want more egghead?

This lesson is for members. Join us? Get access to all 3,000+ tutorials + a community with expert developers around the world.

Unlock This Lesson
1×
Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.

Autoplay

    Conditionally Transition to States with Guards in XState

    xstateXState
    >=4.6.7
    javascriptJavaScript

    Not all transitions should be taken immediately. Occasionally, we would like to conditionally take a transition. We do this through the use of "guards". A "guard" is a predicate function (a function that returns a boolean) that is set on a transition object's cond property (short for "conditional").

    When an event is sent to the machine and it encounters a transition object with a cond property set to a guard function, it will call that function with the current context and event object. If the guard returns true, the transition will be taken, otherwise, it will attempt the next transition for the event, or remain in the current state.

    javascript//...
    EVENT_NAME: {
      target: 'state-name-of-transition-target',
      cond: (context, event) => predicateFunction(context, event)
    }
    Code

    Code

    Become a Member to view code

    You must be a Pro Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    orLog In
    Discuss

    Discuss

    Transcript

    Transcript

    Instructor: Here I have a state machine for a vending machine. It has two states, idle and vending. On idle, I can select an item which currently targets vending as the transition.

    However, that's not how we want our vending machine to work. We don't want them to just be able to select an item without having paid for it. We can do this by adding a guard.

    To start, we're going to change this from being a string to an object of target vending, since it's still the state that we want to target. Next, we're going to add the cond property. The cond property is a predicate function. That's a function that returns a Boolean.

    In this case, we want it to return true when we'd like to take the transition and return false when we don't want it to. Guard functions receive the context and event as arguments. However, in this case, we only need the context.

    We want it to return true when context.deposited is greater than or equal to 100. We're going to update our machine. We'll see that a cond has been set on select item. In fact, it's disabled. We can't select it right now.

    Now, another way to set the condition is rather than setting the function here in place, we can use the second argument to machine, the options object and add guards to that.

    I am going to add a guard down here. We'll create a new conditional function. We'll call it depositedEnough. We'll take the function that we wrote up here. We're going to cut that out and replace it with a string of the same method name, so depositedEnough, and take that function and place it here.

    We're now going to update our machine. We'll see that the visualization has updated to show us that the depositedEnough condition is here. It's also red because it hasn't been met yet.

    Let's open up the state tab. We'll be able to watch the context increase as I deposit quarters. One, two, three, four. DepositedEnough is now green. That condition is true and I can take this transition by firing this event.

    I select my item and it gets vended.