0
# Core Hooks
1
2
The core hooks provide the primary interface for integrating XState actors with React components. These hooks manage actor lifecycle and state synchronization automatically.
3
4
## useActor
5
6
Creates and manages an XState actor with automatic React state synchronization. Returns the current snapshot, send function, and actor reference.
7
8
```typescript { .api }
9
function useActor<TLogic extends AnyActorLogic>(
10
logic: TLogic,
11
options?: ActorOptions<TLogic> & {
12
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
13
}
14
): [SnapshotFrom<TLogic>, Actor<TLogic>['send'], Actor<TLogic>];
15
```
16
17
### Parameters
18
19
- `logic`: The XState actor logic (machine, promise, observable, etc.)
20
- `options`: Optional actor configuration options
21
22
### Returns
23
24
A tuple containing:
25
- `snapshot`: Current actor snapshot/state
26
- `send`: Function to send events to the actor
27
- `actorRef`: The actor reference for direct access
28
29
### Usage Example
30
31
```typescript
32
import { useActor } from "@xstate/react";
33
import { createMachine, assign } from "xstate";
34
35
const counterMachine = createMachine({
36
id: "counter",
37
initial: "idle",
38
context: { count: 0 },
39
states: {
40
idle: {
41
on: {
42
INCREMENT: {
43
actions: assign({ count: ({ context }) => context.count + 1 })
44
}
45
}
46
}
47
}
48
});
49
50
function Counter() {
51
const [state, send, actorRef] = useActor(counterMachine);
52
53
return (
54
<div>
55
<p>Count: {state.context.count}</p>
56
<button onClick={() => send({ type: "INCREMENT" })}>
57
Increment
58
</button>
59
</div>
60
);
61
}
62
```
63
64
### Features
65
66
- Automatic actor lifecycle management (start/stop)
67
- Optimized re-rendering using `useSyncExternalStore`
68
- Development-time validation to prevent common mistakes
69
- SSR compatibility with isomorphic layout effects
70
71
## useActorRef
72
73
Creates an actor reference without automatic state subscription. Useful when you need the actor reference but don't want automatic re-renders.
74
75
```typescript { .api }
76
function useActorRef<TLogic extends AnyActorLogic>(
77
machine: TLogic,
78
options?: ActorOptions<TLogic>,
79
observerOrListener?: Observer<SnapshotFrom<TLogic>> | ((value: SnapshotFrom<TLogic>) => void)
80
): Actor<TLogic>;
81
```
82
83
### Parameters
84
85
- `machine`: The XState actor logic
86
- `options`: Optional actor configuration options
87
- `observerOrListener`: Optional observer or listener function for state changes
88
89
### Returns
90
91
The actor reference for sending events and accessing state.
92
93
### Usage Example
94
95
```typescript
96
import { useActorRef, useSelector } from "@xstate/react";
97
import { createMachine } from "xstate";
98
99
const timerMachine = createMachine({
100
id: "timer",
101
initial: "idle",
102
context: { elapsed: 0 },
103
states: {
104
idle: {
105
on: { START: "running" }
106
},
107
running: {
108
on: { STOP: "idle" }
109
}
110
}
111
});
112
113
function Timer() {
114
const actorRef = useActorRef(timerMachine);
115
const elapsed = useSelector(actorRef, (state) => state.context.elapsed);
116
const isRunning = useSelector(actorRef, (state) => state.matches("running"));
117
118
return (
119
<div>
120
<p>Elapsed: {elapsed}ms</p>
121
<button onClick={() => actorRef.send({ type: isRunning ? "STOP" : "START" })}>
122
{isRunning ? "Stop" : "Start"}
123
</button>
124
</div>
125
);
126
}
127
```
128
129
### Features
130
131
- Manual control over state subscription
132
- Optional observer for custom state change handling
133
- Actor reference persists across re-renders
134
- Supports snapshot rehydration for React Strict Mode
135
136
## useSelector
137
138
Subscribes to a specific part of an actor's state using a selector function. Optimizes re-rendering by only updating when the selected value changes.
139
140
```typescript { .api }
141
function useSelector<
142
TActor extends Pick<AnyActorRef, 'subscribe' | 'getSnapshot'> | undefined,
143
T
144
>(
145
actor: TActor,
146
selector: (
147
snapshot: TActor extends { getSnapshot(): infer TSnapshot } ? TSnapshot : undefined
148
) => T,
149
compare?: (a: T, b: T) => boolean
150
): T;
151
```
152
153
### Parameters
154
155
- `actor`: The actor reference to subscribe to (can be undefined)
156
- `selector`: Function to extract the desired value from the snapshot
157
- `compare`: Optional comparison function (defaults to `===`)
158
159
### Returns
160
161
The selected value from the actor's current snapshot.
162
163
### Usage Example
164
165
```typescript
166
import { useActorRef, useSelector } from "@xstate/react";
167
import { createMachine } from "xstate";
168
169
const appMachine = createMachine({
170
id: "app",
171
initial: "loading",
172
context: {
173
user: null,
174
posts: [],
175
error: null
176
},
177
states: {
178
loading: {
179
on: { LOADED: "idle" }
180
},
181
idle: {
182
on: { ERROR: "error" }
183
},
184
error: {}
185
}
186
});
187
188
function UserProfile() {
189
const appActor = useActorRef(appMachine);
190
191
// Only re-render when user changes
192
const user = useSelector(appActor, (state) => state.context.user);
193
194
// Only re-render when loading state changes
195
const isLoading = useSelector(appActor, (state) => state.matches("loading"));
196
197
// Custom comparison for complex objects
198
const posts = useSelector(
199
appActor,
200
(state) => state.context.posts,
201
(a, b) => a.length === b.length && a.every((post, i) => post.id === b[i].id)
202
);
203
204
if (isLoading) return <div>Loading...</div>;
205
206
return (
207
<div>
208
<h1>{user?.name}</h1>
209
<p>{posts.length} posts</p>
210
</div>
211
);
212
}
213
```
214
215
### Features
216
217
- Efficient re-rendering with custom comparison functions
218
- Works with any actor reference or undefined values
219
- Built on React's `useSyncExternalStoreWithSelector`
220
- Supports complex state selection patterns
221
222
## Common Patterns
223
224
### Conditional Actor Usage
225
226
```typescript
227
function ConditionalComponent({ shouldUseActor }: { shouldUseActor: boolean }) {
228
const [state, send] = useActor(
229
shouldUseActor ? myMachine : createMachine({ initial: "idle", states: { idle: {} } })
230
);
231
232
// Component logic...
233
}
234
```
235
236
### Actor Reference Sharing
237
238
```typescript
239
function Parent() {
240
const actorRef = useActorRef(sharedMachine);
241
242
return (
243
<div>
244
<Child1 actor={actorRef} />
245
<Child2 actor={actorRef} />
246
</div>
247
);
248
}
249
250
function Child1({ actor }: { actor: Actor<typeof sharedMachine> }) {
251
const value = useSelector(actor, (state) => state.context.someValue);
252
return <div>{value}</div>;
253
}
254
```
255
256
### Performance Optimization
257
258
```typescript
259
// Use useSelector with custom comparison for expensive operations
260
const expensiveValue = useSelector(
261
actor,
262
(state) => computeExpensiveValue(state.context.data),
263
(a, b) => a.id === b.id // Only recompute when ID changes
264
);
265
```