Class: PlayerActor<TMachine>
API / @xmachines/play-xstate / PlayerActor
Defined in: packages/play-xstate/src/player-actor.ts:362
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
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 microtask by the watcher itselfSee
- Play RFC
- 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
AbstractActor<AnyActorLogic,EventFromLogic<TMachine>>
Type Parameters
| Type Parameter | Description |
|---|---|
TMachine extends AnyStateMachine | XState v5 state machine type |
Implements
Constructors
Constructor
new PlayerActor<TMachine>( machine, options, input?,restoredSnapshot?): PlayerActor<TMachine>;Defined in: packages/play-xstate/src/player-actor.ts:454
Parameters
| Parameter | Type |
|---|---|
machine | TMachine |
options | PlayerOptions<TMachine> |
input? | InputFrom<TMachine> |
restoredSnapshot? | SnapshotFrom<TMachine> |
Returns
PlayerActor<TMachine>
Overrides
Properties
| Property | Modifier | Type | Description | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|
_parent? | public | AnyActorRef | - | - | AbstractActor._parent | - |
clock | public | Clock | The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions. | - | AbstractActor.clock | - |
currentRoute | public | Computed<string | null> | A TC39 Signal.Computed that derives the current URL path from the active machine state’s meta.route template and the actor’s context. Returns null when the current state has no meta.route, or when the route template cannot be fully resolved (e.g. a required parameter is absent from context). Throws When a required :param placeholder in the route template has no matching value in the actor’s context. Import the class from @xmachines/play-xstate/errors. Example // Returns "/profile/alice" when context.userId === "alice" const route = actor.currentRoute.get(); | - | - | packages/play-xstate/src/player-actor.ts:408 |
currentView | public | State<PlaySpec | null> | Reactive signal containing the current view spec derived from the active state’s meta.view metadata. Emits a fresh object reference whenever the rendered view actually changes — a different state’s view, or a param/context change that alters the resolved spec (including reenter: true re-entries with new params). Snapshots that do not change the rendered view (e.g. context-only assigns) keep the previous reference so downstream providers do not remount the UI on every event. The emitted PlaySpec has its element props enriched with context.params before emission — URL path parameters (e.g. :section?) flow into component props automatically. See mergeRouteParamsIntoProps for the merge priority rules. Returns null when the current state has no meta.view metadata. Example const view = actor.currentView.get(); if (view) { console.log(view.root); // e.g. "root" console.log(view.elements); // @xmachines/json-render-core Spec elements } | - | - | packages/play-xstate/src/player-actor.ts:452 |
id | public | string | The unique identifier for this actor relative to its parent. | - | AbstractActor.id | - |
initialRoute | readonly | string | null | The route derived from the machine’s initial state — fixed at construction, never changes even when the actor is restored from a snapshot. Router bridges compare this against the browser URL to distinguish a deep-link (non-initial URL → router wins) from a restore (initial URL + actor at a different restored route → actor wins). Derived statically from the machine definition via deriveInitialRoute (XState’s pure initialTransition helper): the initial state chain and its meta.route templates are fixed at machine definition time, while :param substitution uses the machine’s real initial context for this actor’s input. No extra actor is ever created, and a restored snapshot never influences the value — it is always the machine’s default initial route. | - | - | packages/play-xstate/src/player-actor.ts:425 |
logic | public | AnyActorLogic | - | - | AbstractActor.logic | - |
options | public | Readonly<ActorOptions<TLogic>> | - | - | AbstractActor.options | - |
ref | public | ActorRef<any, any, any> | - | - | AbstractActor.ref | - |
sessionId | public | string | The globally unique process ID for this invocation. | - | AbstractActor.sessionId | - |
src | public | | string | AnyActorLogic | - | - | AbstractActor.src | - |
state | public | State<ReturnType<TMachine["transition"]>> | Reactive snapshot of current actor state. Infrastructure observes this signal to react to state changes without directly coupling to the actor’s internal state machine implementation. | AbstractActor.state | - | packages/play-xstate/src/player-actor.ts:373 |
system | public | AnyActorSystem | The system to which this actor belongs. | - | AbstractActor.system | - |
systemId | public | string | undefined | - | - | AbstractActor.systemId | - |
Methods
[observable]()
observable: InteropSubscribable<any>;Defined in: xstate
Returns
InteropSubscribable<any>
Inherited from
can()
can(event): boolean;Defined in: packages/play-xstate/src/player-actor.ts:386
Returns whether the actor’s current state can accept the given event.
Typed to the machine’s event union — passing an unknown event type is a compile error. Delegates to the underlying XState actor’s snapshot.
Parameters
| Parameter | Type |
|---|---|
event | EventFromLogic<TMachine> |
Returns
boolean
Example
if (actor.can({ type: "auth.logout" })) { ... }dispose()
dispose(): void;Defined in: packages/play-xstate/src/player-actor.ts:727
Convenience dispose method for cleanup
Per CONTEXT.md: “Both .dispose() convenience method and manual machine.stop()“
Returns
void
getPersistedSnapshot()
getPersistedSnapshot(): Snapshot<unknown>;Defined in: packages/play-xstate/src/player-actor.ts:685
Get the persisted snapshot of the wrapped XState actor.
Suitable for serialization and later restoration via the factory’s
restore.snapshot option.
Returns
Snapshot<unknown>
Overrides
AbstractActor.getPersistedSnapshot
getSnapshot()
getSnapshot(): SnapshotFrom<TMachine>;Defined in: packages/play-xstate/src/player-actor.ts:609
Get current snapshot
Returns
SnapshotFrom<TMachine>
Overrides
on()
on<TType>(type, handler): Subscription;Defined in: packages/play-xstate/src/player-actor.ts:670
Listen for events emitted by the wrapped XState actor via the emit action.
Type Parameters
| Type Parameter |
|---|
TType extends any |
Parameters
| Parameter | Type | Description |
|---|---|---|
type | TType | Emitted event type to listen for, or "*" for all. |
handler | (emitted) => void | Called with each matching emitted event. |
Returns
Subscription with an unsubscribe() method.
Overrides
select()
select<TSelected>(selector, equalityFn?): Readable<TSelected>;Defined in: xstate
Type Parameters
| Type Parameter |
|---|
TSelected |
Parameters
| Parameter | Type |
|---|---|
selector | (snapshot) => TSelected |
equalityFn? | (a, b) => boolean |
Returns
Readable<TSelected>
Inherited from
send()
send(event): void;Defined in: packages/play-xstate/src/player-actor.ts:586
Send an event to the underlying XState actor.
The actor’s state machine guards decide whether the event causes a transition. Pass any event from the machine’s event union — domain events, routing events, etc.
Parameters
| Parameter | Type | Description |
|---|---|---|
event | EventFromLogic<TMachine> | An event from the machine’s EventFromLogic<TMachine> union. |
Returns
void
Throws
When event is not a plain object (null, undefined,
a string, number, etc.). Import the class from @xmachines/play-xstate/errors.
Example
// Domain event (typed to machine's event union)actor.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:541
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:555
Stop the actor and cleanup
Returns
this
Overrides
subscribe()
Call Signature
subscribe(observer): Subscription;Defined in: packages/play-xstate/src/player-actor.ts:631
Subscribe to snapshot updates from the wrapped XState actor.
Accepts an observer object, exactly like XState’s Actor.subscribe.
Parameters
| Parameter | Type | Description |
|---|---|---|
observer | Observer<SnapshotFrom<TMachine>> | Observer with next/error/complete handlers. |
Returns
Subscription with an unsubscribe() method.
Overrides
Call Signature
subscribe( nextListener?, errorListener?, completeListener?): Subscription;Defined in: packages/play-xstate/src/player-actor.ts:642
Subscribe to snapshot updates from the wrapped XState actor.
Accepts listener functions, exactly like XState’s Actor.subscribe.
Parameters
| Parameter | Type | Description |
|---|---|---|
nextListener? | (snapshot) => void | Snapshot listener function. |
errorListener? | (error) => void | Called when the actor errors. |
completeListener? | () => void | Called when the actor completes (reaches a final state). |
Returns
Subscription with an unsubscribe() method.
Overrides
toJSON()
toJSON(): object;Defined in: xstate
Returns
object
| Name | Type | Defined in |
|---|---|---|
id | string | - |
xstate$$type | number | - |