Skip to content
Version: XState v5

Event emitter

Since XState version 5.9.0

State machines in XState have the ability to emit events using the emit(event) action creator. This allows external event handlers to be notified of specific events.

import { setup, emit } from 'xstate';

const machine = setup({
actions: {
emitEvent: emit({ type: 'notification' })
}
}).createMachine({
// ...
on: {
someEvent: {
actions: { type: 'emitEvent' }
}
}
});

const actor = createActor(machine);

actor.on('notification', (event) => {
console.log('Notification received!', event);
});

actor.start();

actor.send({ type: 'someEvent' });
// Logs:
// "Notification received!"
// { type: "notification" }

Emit action creator​

The emit action is a special action that emits an event to any external event handlers. The emitted event can be statically or dynamically defined:

import { setup, emit } from 'xstate';

const machine = setup({
actions: {
// Emitting a statically-defined event
emitStaticEvent: emit({
type: 'someStaticEvent',
data: 42
}),

// Emitting a dynamically-defined event based on context
emitDynamicEvent: emit(({ context }) => ({
type: 'someDynamicEvent',
data: context.someData
}))
}
}).createMachine({
// ...
on: {
someEvent: {
actions: [
{ type: 'emitStaticEvent' },
{ type: 'emitDynamicEvent' }
]
}
}
});

Event handlers​

You can attach event handlers to the actor to listen for emitted events by using actor.on(event, handler):

const someActor = createActor(someMachine);

someActor.on('someEvent', (emittedEvent) => {
// Handle the emitted event
console.log(emittedEvent);
});

someActor.start();

The actor.on(…) method returns a subscription object. You can call .unsubscribe() on it to remove the handler:

const someActor = createActor(someMachine);

const subscription = someActor.on('someEvent', (emittedEvent) => {
// Handle the emitted event
console.log(emittedEvent);
});

someActor.start();

// ...

// Stop listening for events
subscription.unsubscribe();

TypeScript​

You can strongly type emitted events by defining the emitted event types in the types.emitted property of the setup(…) function:

import { setup, emit, createActor } from 'xstate';

const machine = setup({
types: {
emitted: {} as
| { type: 'notification'; message: string; }
| { type: 'error'; error: Error; },
// ...
}
}).createMachine({
// ...
on: {
someEvent: {
actions: [
// Strongly typed emitted event
emit({ type: 'notification', message: 'Hello' })
]
}
}
});

const actor = createActor(machine);

// Strongly typed event handler
actor.on('notification', (event) => {
console.log(event.message); // string
});