Class: PlayerActor<TMachine>
Documentation / @xmachines/play-xstate / PlayerActor
Defined in: packages/play-xstate/src/player-actor.ts:120
Concrete XState actor implementing Play Architecture signal protocol
Extends @xmachines/play-actor!AbstractActor to provide XState v5 integration while maintaining ecosystem compatibility (XState inspection, devtools). This actor wraps an internal XState actor and exposes TC39 Signal-based reactive state for Infrastructure observation.
Capabilities: Implements both @xmachines/play-actor!Routable and @xmachines/play-actor!Viewable interfaces, providing routing and view rendering support.
Architectural Context: Implements Actor Authority (INV-01) by ensuring the
XState machine’s guards control all navigation decisions. Infrastructure observes
the actor’s signals (state, currentRoute, currentView) but cannot directly
manipulate state—all mutations flow through the state machine’s event handlers.
Examples
Basic actor creation and lifecycle
import { setup } from "xstate";import { definePlayer } from "@xmachines/play-xstate";
const machine = setup({}).createMachine({ initial: "idle", states: { idle: { meta: { route: "/", view: { component: "HomePage" } }, }, },});
const createPlayer = definePlayer({ machine });const actor = createPlayer();actor.start();
// Observe signalsconsole.log(actor.currentRoute.get()); // '/'console.log(actor.currentView.get()); // { component: 'HomePage' }Signal lifecycle with watchers (microtask batching)
import { Signal } from "@xmachines/play-signals";
const watcher = new Signal.subtle.Watcher(() => { queueMicrotask(() => { const pending = watcher.getPending(); console.log("State changed:", actor.state.get()); });});
watcher.watch(actor.state);actor.send({ type: "play.route", to: "#about" });// Watcher notification scheduled via microtaskSee
- RFC Play v1
- definePlayer for factory creation
- @xmachines/play-actor!AbstractActor for signal protocol
- @xmachines/play-actor!Routable for routing capability
- @xmachines/play-actor!Viewable for view rendering capability
Remarks
Routing: This actor supports both XState’s route: {} config pattern
and play.route events with parameters. The deriveRoute() function checks
meta.route (Stately pattern) for URL templates with parameter substitution support.
View Signal Pattern: The currentView signal is a direct Signal.State (not
Signal.Computed) to ensure proper watcher propagation in PlayRenderer. Views are
cached and updated at state entry, not computed on every read.
Extends
Type Parameters
| Type Parameter | Description |
|---|---|
TMachine extends AnyStateMachine | XState v5 state machine type |
Implements
Constructors
Constructor
new PlayerActor<TMachine>( machine, catalog, options,input?): PlayerActor<TMachine>;Defined in: packages/play-xstate/src/player-actor.ts:142
Parameters
| Parameter | Type |
|---|---|
machine | TMachine |
catalog | Catalog | null | undefined |
options | PlayerOptions<TMachine> |
input? | InputFrom<TMachine> |
Returns
PlayerActor<TMachine>
Overrides
Properties
| Property | Modifier | Type | Description | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|
_parent? | public | AnyActorRef | - | - | AbstractActor._parent | node_modules/xstate/dist/declarations/src/createActor.d.ts:33 |
catalog | public | Catalog | Component catalog for view resolution Maps component names to actual component implementations. Used by renderers to resolve view.component to actual UI components. | - | - | packages/play-xstate/src/player-actor.ts:140 |
clock | public | Clock | The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions. | - | AbstractActor.clock | node_modules/xstate/dist/declarations/src/createActor.d.ts:25 |
currentRoute | public | Computed<string | null> | Current route signal Computed signal derived from state machine. Infrastructure observes to sync browser URL. Invariant: Passive Infrastructure - Infrastructure reflects route, never decides. Example const watcher = new Signal.subtle.Watcher(() => { const route = actor.currentRoute.get(); console.log('Route changed:', route); }); watcher.watch(actor.currentRoute); | - | - | packages/play-xstate/src/player-actor.ts:138 |
currentView | public | State<ViewMetadata | null> | Current view signal State signal containing UI structure schema from meta.view. Infrastructure renders view. Invariant: Logic-Driven UI - View structure is defined by business logic, not JSX. Example const watcher = new Signal.subtle.Watcher(() => { const view = actor.currentView.get(); console.log('View changed:', view); }); watcher.watch(actor.currentView); | - | - | packages/play-xstate/src/player-actor.ts:139 |
id | public | string | The unique identifier for this actor relative to its parent. | - | AbstractActor.id | node_modules/xstate/dist/declarations/src/createActor.d.ts:28 |
logic | public | AnyActorLogic | - | - | AbstractActor.logic | node_modules/xstate/dist/declarations/src/createActor.d.ts:18 |
options | public | Readonly<ActorOptions<TLogic>> | - | - | AbstractActor.options | node_modules/xstate/dist/declarations/src/createActor.d.ts:26 |
ref | public | ActorRef<any, any, any> | - | - | AbstractActor.ref | node_modules/xstate/dist/declarations/src/createActor.d.ts:34 |
sessionId | public | string | The globally unique process ID for this invocation. | - | AbstractActor.sessionId | node_modules/xstate/dist/declarations/src/createActor.d.ts:38 |
src | public | | string | AnyActorLogic | - | - | AbstractActor.src | node_modules/xstate/dist/declarations/src/createActor.d.ts:42 |
state | public | State<AnyMachineSnapshot> | Reactive snapshot of current actor state. Typed as Signal.State<unknown> at the abstract level; concrete implementations narrow this to the actual snapshot type (e.g., Signal.State<AnyMachineSnapshot> in @xmachines/play-xstate’s PlayerActor). Infrastructure observes this signal to react to state changes without directly coupling to the Actor’s internal state machine implementation. Example // Infrastructure observes state signal const watcher = new Signal.subtle.Watcher(() => { console.log('Actor state changed:', actor.state.get()); }); watcher.watch(actor.state); | AbstractActor.state | - | packages/play-xstate/src/player-actor.ts:137 |
system | public | AnyActorSystem | The system to which this actor belongs. | - | AbstractActor.system | node_modules/xstate/dist/declarations/src/createActor.d.ts:40 |
systemId | public | string | undefined | - | - | AbstractActor.systemId | node_modules/xstate/dist/declarations/src/createActor.d.ts:36 |
Methods
[observable]()
observable: InteropSubscribable<any>;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:153
Returns
InteropSubscribable<any>
Inherited from
dispose()
dispose(): void;Defined in: packages/play-xstate/src/player-actor.ts:434
Convenience dispose method for cleanup
Per CONTEXT.md: “Both .dispose() convenience method and manual machine.stop()“
Returns
void
getPersistedSnapshot()
getPersistedSnapshot(): Snapshot<unknown>;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:152
Obtain the internal state of the actor, which can be persisted.
Returns
Snapshot<unknown>
Remarks
The internal state can be persisted from any actor, not only machines.
Note that the persisted state is not the same as the snapshot from Actor.getSnapshot. Persisted state represents the internal state of the actor, while snapshots represent the actor’s last emitted value.
Can be restored with ActorOptions.state
See
https://stately.ai/docs/persistence
Inherited from
AbstractActor.getPersistedSnapshot
getSnapshot()
getSnapshot(): SnapshotFrom<TMachine>;Defined in: packages/play-xstate/src/player-actor.ts:307
Get current snapshot
Returns
SnapshotFrom<TMachine>
Overrides
on()
on<TType>(type, handler): Subscription;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:115
Type Parameters
| Type Parameter |
|---|
TType extends any |
Parameters
| Parameter | Type |
|---|---|
type | TType |
handler | (emitted) => void |
Returns
Inherited from
send()
send(event): void;Defined in: packages/play-xstate/src/player-actor.ts:282
Send event to actor
Forwards events to the underlying XState actor. The actor’s state machine guards determine whether each event is valid from the current state.
Parameters
| Parameter | Type | Description |
|---|---|---|
event | PlayEvent | Any event object with a type property |
Returns
void
Example
// Domain eventactor.send({ type: "auth.login", userId: "123" });
// Routing eventactor.send({ type: "play.route", to: "#home" });Overrides
start()
start(): this;Defined in: packages/play-xstate/src/player-actor.ts:239
Start the actor
Per RESEARCH.md Pitfall 1: Always call start() after creation
Returns
this
Overrides
stop()
stop(): this;Defined in: packages/play-xstate/src/player-actor.ts:253
Stop the actor and cleanup
Returns
this
Overrides
subscribe()
Call Signature
subscribe(observer): Subscription;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:113
Subscribe an observer to an actor’s snapshot values.
Parameters
| Parameter | Type | Description |
|---|---|---|
observer | Observer<any> | Either a plain function that receives the latest snapshot, or an observer object whose .next(snapshot) method receives the latest snapshot |
Returns
Remarks
The observer will receive the actor’s snapshot value when it is emitted. The observer can be:
- A plain function that receives the latest snapshot, or
- An observer object whose
.next(snapshot)method receives the latest snapshot
Examples
// Observer as a plain functionconst subscription = actor.subscribe((snapshot) => { console.log(snapshot);});// Observer as an objectconst subscription = actor.subscribe({ next(snapshot) { console.log(snapshot); }, error(err) { // ... }, complete() { // ... },});The return value of actor.subscribe(observer) is a subscription object
that has an .unsubscribe() method. You can call
subscription.unsubscribe() to unsubscribe the observer:
const subscription = actor.subscribe((snapshot) => { // ...});
// Unsubscribe the observersubscription.unsubscribe();When the actor is stopped, all of its observers will automatically be unsubscribed.
Inherited from
Call Signature
subscribe( nextListener?, errorListener?, completeListener?): Subscription;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:114
Subscribe an observer to an actor’s snapshot values.
Parameters
| Parameter | Type |
|---|---|
nextListener? | (snapshot) => void |
errorListener? | (error) => void |
completeListener? | () => void |
Returns
Remarks
The observer will receive the actor’s snapshot value when it is emitted. The observer can be:
- A plain function that receives the latest snapshot, or
- An observer object whose
.next(snapshot)method receives the latest snapshot
Examples
// Observer as a plain functionconst subscription = actor.subscribe((snapshot) => { console.log(snapshot);});// Observer as an objectconst subscription = actor.subscribe({ next(snapshot) { console.log(snapshot); }, error(err) { // ... }, complete() { // ... },});The return value of actor.subscribe(observer) is a subscription object
that has an .unsubscribe() method. You can call
subscription.unsubscribe() to unsubscribe the observer:
const subscription = actor.subscribe((snapshot) => { // ...});
// Unsubscribe the observersubscription.unsubscribe();When the actor is stopped, all of its observers will automatically be unsubscribed.
Inherited from
toJSON()
toJSON(): object;Defined in: node_modules/xstate/dist/declarations/src/createActor.d.ts:135
Returns
object
| Name | Type | Defined in |
|---|---|---|
id | string | node_modules/xstate/dist/declarations/src/createActor.d.ts:137 |
xstate$$type | number | node_modules/xstate/dist/declarations/src/createActor.d.ts:136 |