# Events

An event is what causes a state machine to transition from its current state to its next state. All state transitions in a state machine are due to these events; state cannot change unless some stimulus (the event) causes it to change.

An event is an object with a type property, signifying what type of event it is:

const timerEvent = {
  type: 'TIMER'
};

As shorthand, in XState, events that only have a type can be represented just by their string type:

// equivalent to { type: 'TIMER' }
const timerEvent = 'TIMER';

Event objects can also have other properties, which represent data associated with the event:

const keyDownEvent = {
  type: 'keydown',
  key: 'Enter'
};

# Sending Events

As explained in the transitions guide, a transition defines what the next state will be given the current state and the event, defined on its on: { ... } property. This can be observed by passing an event into the transition method:

import { Machine } from 'xstate';

const lightMachine = Machine({
  /* ... */
});

const { initialState } = lightMachine;

let nextState = lightMachine.transition(initialState, 'TIMER'); // string event
console.log(nextState.value);
// => 'yellow'

nextState = lightMachine.transition(nextState, { type: 'TIMER' }); // event object
console.log(nextState.value);
// => 'red'

By specifying the event type on the type property, many native events, such as DOM events, are compatible and can be used directly with XState:

import { Machine, interpret } from 'xstate';

const mouseMachine = Machine({
  /* ... */
});
const mouseService = interpret(mouseMachine).start();

window.addEventListener('mousemove', event => {
  // event can be sent directly to service
  mouseService.send(event);
});

# Null Events

A null event is an event that has no type, and occurs immediately once a state is entered. In transitions, it is represented by an empty string (''):

// contrived example
const skipMachine = Machine({
  id: 'skip',
  initial: 'one',
  states: {
    one: {
      on: { CLICK: 'two' }
    },
    two: {
      // null event '' always occurs once state is entered
      // immediately take the transition to 'three'
      on: { '': 'three' }
    },
    three: {
      type: 'final'
    }
  }
});

const { initialState } = skipMachine;
const nextState = skipMachine.transition(initialState, 'CLICK');

console.log(nextState.value);
// => 'three'

There are many use cases for null events, especially when defining transient transitions, where a (potentially transient) state immediately determines what the next state should be based on conditions:

const isAdult = ({ age }) => age >= 18;
const isMinor = ({ age }) => age < 18;

const ageMachine = Machine({
  id: 'age',
  context: { age: undefined }, // age unknown
  initial: 'unknown',
  states: {
    unknown: {
      on: {
        // immediately take transition that satisfies conditional guard.
        // otherwise, no transition occurs
        '': [
          { target: 'adult', cond: isAdult },
          { target: 'child', cond: isMinor }
        ]
      }
    },
    adult: { type: 'final' },
    child: { type: 'final' }
  }
});

console.log(ageMachine.initialState.value);
// => 'unknown'

const personData = { age: 28 };

const personMachine = ageMachine.withContext(personData);

console.log(personMachine.initialState.value);
// => 'adult'

# SCXML

Events in SCXML contain information relevant to the source of the event, and have a different schema than event objects in XState. Internally, event objects are converted to SCXML events for compatibility.

SCXML events include:

  • name - a character string giving the name of the event. This is equivalent to the .type property of an XState event.
  • type - the event type: 'platform', 'external', or 'internal'.
    • platform events are raised by the platform itself, such as error events.
    • internal events are raised by raise(...) actions or by send(...) actions with target: '_internal'.
    • external events describe all other events.
  • sendid - the send ID of the triggering send(...) action.
  • origin - a string that allows the receiver of this event to send(...) a response event back to the origin.
  • origintype - used with origin
  • invokeid - the invoke ID of the invocation that triggered the child service.
  • data - any data that the sending entity chose to include with this event. This is equivalent to an XState event object.

The SCXML event form of all XState events is present in the _event property of action and guard meta objects (third argument):




 
 



 
 





// ...
{
  actions: {
    someAction: (context, event, { _event }) => {
      console.log(_event); // SCXML event
    };
  },
  guards: {
    someGuard: (context, event, { _event }) => {
      console.log(_event); // SCXML event
    }
  }
}
// ..