Documentation Index
Fetch the complete documentation index at: https://mintlify.com/statelyai/xstate/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The useActor function creates an actor from XState logic and manages its lifecycle within a Svelte component.
function useActor<TLogic extends AnyActorLogic>(
logic: TLogic,
options?: ActorOptions<TLogic>
): {
snapshot: Readable<SnapshotFrom<TLogic>>;
send: (event: EventFromLogic<TLogic>) => void;
actorRef: Actor<TLogic>;
}
Basic Usage
<script>
import { useActor } from '@xstate/svelte';
import { createMachine } from 'xstate';
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: {
on: { TOGGLE: 'active' }
},
active: {
on: { TOGGLE: 'inactive' }
}
}
});
const { snapshot, send } = useActor(toggleMachine);
</script>
<div>
<p>State: {$snapshot.value}</p>
<button on:click={() => send({ type: 'TOGGLE' })}>
Toggle
</button>
</div>
With Options
Pass options to configure the actor:
<script>
import { useActor } from '@xstate/svelte';
import { createMachine } from 'xstate';
const machine = createMachine({
context: ({ input }) => ({
userId: input.userId,
data: null
}),
// ...
});
const { snapshot, send } = useActor(machine, {
input: { userId: '123' },
inspect: (event) => {
console.log('Inspector:', event);
}
});
</script>
Accessing the Actor Ref
The actorRef allows direct interaction with the underlying actor:
<script>
import { useActor } from '@xstate/svelte';
import { onMount, onDestroy } from 'svelte';
import { myMachine } from './myMachine';
const { snapshot, send, actorRef } = useActor(myMachine);
// Subscribe to state changes
let subscription;
onMount(() => {
subscription = actorRef.subscribe((state) => {
console.log('State changed:', state);
});
});
onDestroy(() => {
subscription?.unsubscribe();
});
// Get current snapshot at any time
function logCurrentState() {
const currentState = actorRef.getSnapshot();
console.log(currentState);
}
</script>
Reactive Store
The snapshot is a Svelte readable store that automatically updates:
<script>
import { useActor } from '@xstate/svelte';
import { fetchMachine } from './fetchMachine';
const { snapshot, send } = useActor(fetchMachine);
// Reactive statements based on snapshot
$: isLoading = $snapshot.matches('loading');
$: data = $snapshot.context.data;
$: hasError = $snapshot.matches('error');
</script>
<div>
{#if isLoading}
<p>Loading...</p>
{:else if hasError}
<p>Error occurred</p>
{:else}
<pre>{JSON.stringify(data, null, 2)}</pre>
{/if}
</div>
useMachine Alias
The useMachine function is an alias for useActor with the same API:
<script>
import { useMachine } from '@xstate/svelte';
import { createMachine } from 'xstate';
const machine = createMachine({
// ...
});
// useMachine and useActor are identical
const { snapshot, send, actorRef } = useMachine(machine);
</script>
Lifecycle Management
The actor lifecycle is automatically managed:
-
Immediate Start
- Actor is created and started immediately:
createActor(logic, options).start()
-
Component Destroy (
onDestroy)
- Actor is stopped via
actorRef.stop()
<script>
import { useActor } from '@xstate/svelte';
import { myMachine } from './myMachine';
// Actor starts immediately
const { snapshot, send } = useActor(myMachine);
// Actor automatically stops when component is destroyed
</script>
Multiple Actors
You can create multiple actors in a single component:
<script>
import { useActor } from '@xstate/svelte';
import { authMachine, dataMachine } from './machines';
const auth = useActor(authMachine);
const data = useActor(dataMachine);
</script>
<div>
<p>Auth state: {$auth.snapshot.value}</p>
<p>Data state: {$data.snapshot.value}</p>
<button on:click={() => auth.send({ type: 'LOGIN' })}>
Login
</button>
<button on:click={() => data.send({ type: 'FETCH' })}>
Fetch Data
</button>
</div>
With Context
Share actors across components using Svelte’s context API:
<script>
import { setContext } from 'svelte';
import { useActor } from '@xstate/svelte';
import { appMachine } from './appMachine';
import Child from './Child.svelte';
const actor = useActor(appMachine);
setContext('actor', actor);
</script>
<div>
<h1>App State: {$actor.snapshot.value}</h1>
<Child />
</div>
TypeScript
The function is fully typed:
import { setup } from 'xstate';
import { useActor } from '@xstate/svelte';
import type { Readable } from 'svelte/store';
const machine = setup({
types: {
context: {} as { count: number; name: string },
events: {} as
| { type: 'INCREMENT' }
| { type: 'DECREMENT' }
| { type: 'SET_NAME'; name: string }
}
}).createMachine({
context: { count: 0, name: '' },
// ...
});
const { snapshot, send, actorRef } = useActor(machine);
// snapshot is Readable<SnapshotFrom<typeof machine>>
// All types are inferred
snapshot.subscribe((state) => {
state.context.count; // number
state.context.name; // string
});
// TypeScript validates events
send({ type: 'INCREMENT' }); // ✅
send({ type: 'SET_NAME', name: 'Alice' }); // ✅
send({ type: 'INVALID' }); // ❌ TypeScript error
Implementation Details
The useActor function:
- Creates an actor using
useActorRef(logic, options)
- Gets the initial snapshot
- Creates a Svelte readable store
- Subscribes to actor changes in the store’s start function
- Updates the store only when snapshot reference changes
- Automatically unsubscribes when the store has no subscribers
useActorRef
Get actor ref without reactive store
useSelector
Select derived values from snapshots