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 hook creates an actor from XState logic and manages its lifecycle within a SolidJS component.
function useActor<TLogic extends AnyActorLogic>(
logic: TLogic,
options?: ActorOptions<TLogic>
): [
SnapshotFrom<TLogic>,
(event: EventFromLogic<TLogic>) => void,
ActorRefFrom<TLogic>
]
Basic Usage
import { useActor } from '@xstate/solid';
import { createMachine } from 'xstate';
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: {
on: { TOGGLE: 'active' }
},
active: {
on: { TOGGLE: 'inactive' }
}
}
});
export const Toggle = () => {
const [snapshot, send] = useActor(toggleMachine);
return (
<div>
<p>State: {snapshot.value}</p>
<button onclick={() => send({ type: 'TOGGLE' })}>
Toggle
</button>
</div>
);
};
With Options
Pass options to configure the actor:
import { useActor } from '@xstate/solid';
import { createMachine } from 'xstate';
const machine = createMachine({
context: ({ input }) => ({
userId: input.userId,
data: null
}),
// ...
});
export const App = () => {
const [snapshot, send] = useActor(machine, {
input: { userId: '123' },
inspect: (event) => {
console.log('Inspector:', event);
}
});
return <div>{/* ... */}</div>;
};
Accessing the Actor Ref
The third element of the tuple is the actor ref:
import { useActor } from '@xstate/solid';
import { createEffect, onCleanup } from 'solid-js';
import { myMachine } from './myMachine';
export const App = () => {
const [snapshot, send, actorRef] = useActor(myMachine);
// Subscribe to state changes
createEffect(() => {
const subscription = actorRef.subscribe((state) => {
console.log('State changed:', state);
});
onCleanup(() => subscription.unsubscribe());
});
// Get current snapshot at any time
const logState = () => {
console.log(actorRef.getSnapshot());
};
return (
<div>
<button onclick={logState}>Log State</button>
</div>
);
};
Granular Reactivity
SolidJS tracks property access for fine-grained reactivity:
import { useActor } from '@xstate/solid';
import { fetchMachine } from './fetchMachine';
export const App = () => {
const [snapshot, send] = useActor(fetchMachine);
// Component only re-renders when these specific properties change
const isLoading = () => snapshot.matches('loading');
const data = () => snapshot.context.data;
const hasError = () => snapshot.matches('error');
return (
<div>
<Show when={isLoading()}>
<p>Loading...</p>
</Show>
<Show when={hasError()}>
<p>Error occurred</p>
</Show>
<Show when={!isLoading() && !hasError()}>
<pre>{JSON.stringify(data(), null, 2)}</pre>
</Show>
</div>
);
};
useMachine Alias
The useMachine hook is an alias for useActor with the same API:
import { useMachine } from '@xstate/solid';
import { createMachine } from 'xstate';
const machine = createMachine({
// ...
});
export const App = () => {
// useMachine and useActor are identical
const [snapshot, send, actorRef] = useMachine(machine);
return <div>{/* ... */}</div>;
};
Lifecycle Management
The actor lifecycle is automatically managed:
-
Component Mount (
onMount)
- Actor is started via
actorRef.start()
- Cleanup registered via
onCleanup
-
Component Unmount
- Actor is stopped via
actorRef.stop()
import { useActor } from '@xstate/solid';
import { myMachine } from './myMachine';
export const App = () => {
// Actor starts on mount
const [snapshot, send] = useActor(myMachine);
// Actor stops on unmount
return <div>{/* ... */}</div>;
};
Multiple Actors
You can create multiple actors in a single component:
import { useActor } from '@xstate/solid';
import { authMachine, dataMachine } from './machines';
export const App = () => {
const [authSnapshot, sendAuth] = useActor(authMachine);
const [dataSnapshot, sendData] = useActor(dataMachine);
return (
<div>
<p>Auth state: {authSnapshot.value}</p>
<p>Data state: {dataSnapshot.value}</p>
<button onclick={() => sendAuth({ type: 'LOGIN' })}>
Login
</button>
<button onclick={() => sendData({ type: 'FETCH' })}>
Fetch Data
</button>
</div>
);
};
With Context
Share actors across components using SolidJS’s context API:
import { createContext, useContext } from 'solid-js';
import { useActor } from '@xstate/solid';
import { appMachine } from './appMachine';
import Child from './Child';
const ActorContext = createContext();
export const Parent = () => {
const actor = useActor(appMachine);
return (
<ActorContext.Provider value={actor}>
<div>
<h1>App State: {actor[0].value}</h1>
<Child />
</div>
</ActorContext.Provider>
);
};
export const useAppActor = () => useContext(ActorContext);
Derived Values
Create derived values using SolidJS’s createMemo:
import { useActor } from '@xstate/solid';
import { createMemo } from 'solid-js';
import { cartMachine } from './cartMachine';
export const Cart = () => {
const [snapshot] = useActor(cartMachine);
// Memoized derived values
const itemCount = createMemo(() => snapshot.context.items.length);
const totalPrice = createMemo(() => {
return snapshot.context.items.reduce(
(sum, item) => sum + item.price * item.quantity,
0
);
});
return (
<div>
<p>Items: {itemCount()}</p>
<p>Total: ${totalPrice().toFixed(2)}</p>
</div>
);
};
TypeScript
The hook is fully typed:
import { setup } from 'xstate';
import { useActor } from '@xstate/solid';
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: '' },
// ...
});
export const App = () => {
const [snapshot, send, actorRef] = useActor(machine);
// All types are inferred
snapshot.context.count; // number
snapshot.context.name; // string
// TypeScript validates events
send({ type: 'INCREMENT' }); // ✅
send({ type: 'SET_NAME', name: 'Alice' }); // ✅
send({ type: 'INVALID' }); // ❌ TypeScript error
return <div>{/* ... */}</div>;
};
Implementation Details
The useActor hook:
- Creates an actor using
useActorRef(logic, options)
- Uses
fromActorRef to create a tracked accessor for the snapshot
- Returns a tuple of
[snapshot, send, actorRef]
- The snapshot is tracked by SolidJS’s reactivity system
- Component only re-renders when accessed properties change
useActorRef
Get actor ref without reactive tracking
fromActorRef
Subscribe to existing actors