Skip to content

Class: PlayerActor<TMachine>

API / @xmachines/play-xstate / index / PlayerActor

Defined in: packages/play-xstate/src/player-actor.ts:144

The concrete XState actor. It implements the atom protocol of the Play Architecture

The class extends the Actor class of XState directly, and it implements @xmachines/play-actor!PlayActor. It gives you the XState v5 integration, and it keeps the compatibility with the ecosystem, such as the XState inspection and the devtools. The constructor of the base class receives the machine. Therefore a PlayerActor is the XState actor, and it is no wrapper around one: every member of the XState Actor class works on the state of this instance, and this class adds the reactive state on the atoms for the observation by the infrastructure.

Capabilities: the class implements both the @xmachines/play-router!index.Routable interface and the @xmachines/play-view!index.Viewable interface. It therefore supports the routing and the view rendering.

Architectural context: the class implements Actor Authority (INV-01), because the guards of the XState machine control every decision of the navigation. The infrastructure observes the atoms of the actor (state, currentRoute, and currentView), but it changes no state directly: every change goes through the event handlers of the state machine.

Examples

The creation of an actor, and its lifecycle

import { setup } from "xstate";
import { definePlayer, compose, PlayerActor } from "@xmachines/play-xstate";
const machine = setup({}).createMachine({
initial: "idle",
states: {
idle: {
meta: {
route: "/",
// A view spec needs `root` and `elements`. Every other shape derives null.
view: {
root: "home",
elements: { home: { type: "HomePage", props: {}, children: [] } },
},
},
},
},
});
const createPlayer = definePlayer({ machine });
const actor = createPlayer();
actor.start();
// Observe the atoms
console.log(actor.currentRoute.get()); // '/'
console.log(actor.currentView.get()?.root); // 'home'

The atom lifecycle with a watch

import { watchAtom } from "@xmachines/play-atom";
const stop = watchAtom(actor.state, (snapshot) => {
console.log("State changed:", snapshot.value);
});
actor.send({ type: "play.route", to: "#about" });
// watchAtom delivers the new value from a microtask
stop();

See

Remarks

The routing: this actor supports the route: {} config pattern of XState and also a play.route event with parameters. The deriveRoute() function reads meta.route, which is the Stately pattern, for a URL template, and it substitutes each parameter.

The pattern of the view atom: withView of @xmachines/play-xstate/view adds currentView, and that atom is a COMPUTED atom over state. One write for each transition — state.set(snapshot) — therefore reaches the view and the route in one flush, and no subscriber reads the new state beside an old derivation. The atom memoizes the result, so a repeated read computes no view again.

Extends

Type Parameters

Type ParameterDescription
TMachine extends AnyStateMachineThe type of the XState v5 state machine

Implements

Constructors

Constructor

new PlayerActor<TMachine>(
machine,
options,
input?,
restoredSnapshot?
): PlayerActor<TMachine>;

Defined in: packages/play-xstate/src/player-actor.ts:242

Parameters

ParameterType
machineTMachine
optionsPlayerOptions<TMachine>
input?InputFrom<TMachine>
restoredSnapshot?Snapshot<unknown>

Returns

PlayerActor<TMachine>

Overrides

Actor<TMachine>.constructor

Properties

PropertyModifierTypeDescriptionInherited fromDefined in
_parent?publicAnyActorRef-Actor._parent-
clockpublicClockThe clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.Actor.clock-
idpublicstringThe unique identifier for this actor relative to its parent.Actor.id-
logicpublicTMachine-Actor.logic-
optionspublicReadonly<ActorOptions<TLogic>>-Actor.options-
refpublicActorRef<SnapshotFrom<TMachine>, EventFromLogic<TMachine>, EmittedFrom<TMachine>>-Actor.ref-
sessionIdpublicstringThe globally unique process ID for this invocation.Actor.sessionId-
srcpublic| string | AnyActorLogic-Actor.src-
statepublicAtom<ReturnType<TMachine["transition"]>>The reactive snapshot of the current actor state. The infrastructure observes this atom, and it reacts to each state change. It therefore holds no coupling to the internal state machine of the actor.-packages/play-xstate/src/player-actor.ts:208
systempublicAnyActorSystemThe system to which this actor belongs.Actor.system-
systemIdpublicstring | undefined-Actor.systemId-

Methods

[observable]()

observable: InteropSubscribable<SnapshotFrom<TMachine>>;

Defined in: xstate

Returns

InteropSubscribable<SnapshotFrom<TMachine>>

Inherited from

Actor.[observable]

can()

can(event): boolean;

Defined in: packages/play-xstate/src/player-actor.ts:221

Tells you if the current state of the actor accepts the given event.

The type is the event union of the machine. An unknown event type is therefore a compile error. The method evaluates the event against the snapshot atom.

Parameters

ParameterType
eventEventFromLogic<TMachine>

Returns

boolean

Example

if (actor.can({ type: "auth.logout" })) { ... }

getPersistedSnapshot()

getPersistedSnapshot(options?): Snapshot<unknown>;

Defined in: packages/play-xstate/src/player-actor.ts:555

Returns the persisted snapshot of this actor.

Use it to serialize the state, and to restore it later with the restore.snapshot option of the factory.

Parameters

ParameterType
options?unknown

Returns

Snapshot<unknown>

Overrides

Actor.getPersistedSnapshot;

getSnapshot()

getSnapshot(): SnapshotFrom<TMachine>;

Defined in: xstate

Read an actor’s snapshot synchronously.

Returns

SnapshotFrom<TMachine>

Remarks

The snapshot represent an actor’s last emitted value.

When an actor receives an event, its internal state may change. An actor may emit a snapshot when a state transition occurs.

Note that some actors, such as callback actors generated with fromCallback, will not emit snapshots.

See

Inherited from

Actor.getSnapshot;

on()

on<TType>(type, handler): Subscription;

Defined in: xstate

Type Parameters

Type Parameter
TType extends any

Parameters

ParameterType
typeTType
handler(emitted) => void

Returns

Subscription

Inherited from

Actor.on;

select()

select<TSelected>(selector, equalityFn?): Readable<TSelected>;

Defined in: xstate

Type Parameters

Type Parameter
TSelected

Parameters

ParameterType
selector(snapshot) => TSelected
equalityFn?(a, b) => boolean

Returns

Readable<TSelected>

Inherited from

Actor.select;

send()

send(event): void;

Defined in: packages/play-xstate/src/player-actor.ts:432

Sends an event to this actor.

The guards of the state machine of the actor decide if the event causes a transition. Give any event of the event union of the machine: a domain event, a routing event, and so on.

Parameters

ParameterTypeDescription
eventEventFromLogic<TMachine>An event of the EventFromLogic<TMachine> union of the machine.

Returns

void

Throws

When event is not a plain object, for example null, undefined, a string, or a number. Import the class from @xmachines/play-xstate/errors.

Example

// A domain event, with the type of the event union of the machine
actor.send({ type: "auth.login", userId: "123" });
// A routing event
actor.send({ type: "play.route", to: "#home" });

Implementation of

PlayActor.send

Overrides

Actor.send;

start()

start(): this;

Defined in: packages/play-xstate/src/player-actor.ts:358

Starts the actor.

The method fires onStart on each real start, which is every transition from “not running” to “running”. A start after a stop is such a transition, and XState permits it: its own start() stops only while the actor RUNS already. A second call while the actor runs fires no hook. Therefore a defensive double mount runs the side effects of onStart one time for one real start.

Returns

this

Overrides

Actor.start;

stop()

stop(): this;

Defined in: packages/play-xstate/src/player-actor.ts:388

Stops the actor and cleans up.

The method fires onStop only when the actor ran. This matches XState, where a stop of an actor that never started, or of an actor that stopped already, does nothing and tears nothing down. Therefore the paired cleanup runs never two times, and it runs never against a resource that onStart did not take. A stop does not close the actor for ever: a later start() is a new lifecycle, and it fires onStart again.

Returns

this

Overrides

Actor.stop;

subscribe()

Call Signature

subscribe(observer): Subscription;

Defined in: packages/play-xstate/src/player-actor.ts:493

Subscribes to the snapshot updates of this actor.

The method accepts an observer object, exactly like Actor.subscribe of XState.

Parameters
ParameterTypeDescription
observerObserver<SnapshotFrom<TMachine>>The observer, with a next, an error, and a complete handler.
Returns

Subscription

The subscription, with an unsubscribe() method.

Overrides
Actor.subscribe;

Call Signature

subscribe(
nextListener?,
errorListener?,
completeListener?
): Subscription;

Defined in: packages/play-xstate/src/player-actor.ts:504

Subscribes to the snapshot updates of this actor.

The method accepts listener functions, exactly like Actor.subscribe of XState.

Parameters
ParameterTypeDescription
nextListener?(snapshot) => voidThe listener function of each snapshot.
errorListener?(error) => voidThe actor calls it on an error.
completeListener?() => voidThe actor calls it when it completes, which means that it reaches a final state.
Returns

Subscription

The subscription, with an unsubscribe() method.

Overrides
Actor.subscribe;

toJSON()

toJSON(): object;

Defined in: xstate

Returns

object

NameTypeDefined in
idstring-
xstate$$typenumber-

Inherited from

Actor.toJSON;