-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
useActorRef.ts
73 lines (64 loc) · 1.84 KB
/
useActorRef.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { useEffect, useState } from 'react';
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
import {
Actor,
ActorOptions,
AnyActorLogic,
AnyStateMachine,
Observer,
SnapshotFrom,
createActor,
toObserver
} from 'xstate';
import { stopRootWithRehydration } from './stopRootWithRehydration';
export function useIdleActorRef<TLogic extends AnyActorLogic>(
logic: TLogic,
options: Partial<ActorOptions<TLogic>>
): Actor<TLogic> {
let [[currentConfig, actorRef], setCurrent] = useState(() => {
const actorRef = createActor(logic, options);
return [logic.config, actorRef];
});
if (logic.config !== currentConfig) {
const newActorRef = createActor(logic, {
...options,
snapshot: (actorRef.getPersistedSnapshot as any)({
__unsafeAllowInlineActors: true
})
});
setCurrent([logic.config, newActorRef]);
actorRef = newActorRef;
}
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
useIsomorphicLayoutEffect(() => {
(actorRef.logic as any as AnyStateMachine).implementations = (
logic as any as AnyStateMachine
).implementations;
});
return actorRef;
}
export function useActorRef<TLogic extends AnyActorLogic>(
machine: TLogic,
options: ActorOptions<TLogic> = {},
observerOrListener?:
| Observer<SnapshotFrom<TLogic>>
| ((value: SnapshotFrom<TLogic>) => void)
): Actor<TLogic> {
const actorRef = useIdleActorRef(machine, options);
useEffect(() => {
if (!observerOrListener) {
return;
}
let sub = actorRef.subscribe(toObserver(observerOrListener));
return () => {
sub.unsubscribe();
};
}, [observerOrListener]);
useEffect(() => {
actorRef.start();
return () => {
stopRootWithRehydration(actorRef);
};
}, [actorRef]);
return actorRef;
}