@xstate/react 7.0.0-alpha.3 → 7.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/declarations/src/useActor.d.ts +2 -4
- package/dist/declarations/src/useActorRef.d.ts +3 -7
- package/dist/declarations/src/useMachine.d.ts +2 -4
- package/dist/xstate-react.cjs.js +19 -14
- package/dist/xstate-react.development.cjs.js +28 -14
- package/dist/xstate-react.development.esm.js +30 -16
- package/dist/xstate-react.esm.js +20 -15
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -49,4 +49,4 @@ export const Toggler = () => {
|
|
|
49
49
|
|
|
50
50
|
<!-- observer lifecycle from src/useActorRef.ts -->
|
|
51
51
|
|
|
52
|
-
Pass a snapshot listener or observer as the third argument to `useActorRef(logic, options, observer)`. It subscribes before the actor starts. When
|
|
52
|
+
Pass a snapshot listener or observer as the third argument to `useActorRef(logic, options, observer)`. It subscribes before the actor starts. When the hook replaces the actor (after an external stop, or a Fast Refresh that cannot keep it), the observer follows the replacement, even when the callback identity stays the same. Unmounting unsubscribes the observer and stops the actor.
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyActorLogic, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
1
|
+
import { Actor, ActorOptions, AnyActorLogic, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys, type RequiredActorOptionsFor } from 'xstate';
|
|
2
2
|
export declare function useActor<TLogic extends AnyActorLogic>(logic: TLogic, ...[options]: ConditionalRequired<[
|
|
3
|
-
options?: ActorOptions<TLogic> &
|
|
4
|
-
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
5
|
-
}
|
|
3
|
+
options?: ActorOptions<TLogic> & RequiredActorOptionsFor<TLogic>
|
|
6
4
|
], IsNotNever<RequiredActorOptionsKeys<TLogic>>>): [SnapshotFrom<TLogic>, Actor<TLogic>['send'], Actor<TLogic>];
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyActorLogic, Observer, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
1
|
+
import { Actor, ActorOptions, AnyActorLogic, Observer, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys, type RequiredActorOptionsFor } from 'xstate';
|
|
2
2
|
export declare function useIdleActorRef<TLogic extends AnyActorLogic>(logic: TLogic, ...[options]: ConditionalRequired<[
|
|
3
|
-
options?: ActorOptions<TLogic> &
|
|
4
|
-
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
5
|
-
}
|
|
3
|
+
options?: ActorOptions<TLogic> & RequiredActorOptionsFor<TLogic>
|
|
6
4
|
], IsNotNever<RequiredActorOptionsKeys<TLogic>>>): [Actor<TLogic>, (actorRef: Actor<TLogic>) => void];
|
|
7
5
|
export declare function useActorLifecycle<TLogic extends AnyActorLogic>(actorRef: Actor<TLogic>, setActorRef: (actorRef: Actor<TLogic>) => void, createReplacement: () => Actor<TLogic>): void;
|
|
8
6
|
export declare function useActorRef<TLogic extends AnyActorLogic>(machine: TLogic, ...[options, observerOrListener]: IsNotNever<RequiredActorOptionsKeys<TLogic>> extends true ? [
|
|
9
|
-
options: ActorOptions<TLogic> &
|
|
10
|
-
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
11
|
-
},
|
|
7
|
+
options: ActorOptions<TLogic> & RequiredActorOptionsFor<TLogic>,
|
|
12
8
|
observerOrListener?: Observer<SnapshotFrom<TLogic>> | ((value: SnapshotFrom<TLogic>) => void)
|
|
13
9
|
] : [
|
|
14
10
|
options?: ActorOptions<TLogic>,
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyStateMachine, StateFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
1
|
+
import { Actor, ActorOptions, AnyStateMachine, StateFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys, type RequiredActorOptionsFor } from 'xstate';
|
|
2
2
|
/** @alias useActor */
|
|
3
3
|
export declare function useMachine<TMachine extends AnyStateMachine>(machine: TMachine, ...[options]: ConditionalRequired<[
|
|
4
|
-
options?: ActorOptions<TMachine> &
|
|
5
|
-
[K in RequiredActorOptionsKeys<TMachine>]: unknown;
|
|
6
|
-
}
|
|
4
|
+
options?: ActorOptions<TMachine> & RequiredActorOptionsFor<TMachine>
|
|
7
5
|
], IsNotNever<RequiredActorOptionsKeys<TMachine>>>): [StateFrom<TMachine>, Actor<TMachine>['send'], Actor<TMachine>];
|
package/dist/xstate-react.cjs.js
CHANGED
|
@@ -32,23 +32,28 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
32
32
|
var useIsomorphicLayoutEffect__default = /*#__PURE__*/_interopDefault(useIsomorphicLayoutEffect);
|
|
33
33
|
|
|
34
34
|
function useIdleActorRef(logic, ...[options]) {
|
|
35
|
-
|
|
35
|
+
const [actorRef, setActorRef] = React.useState(() => {
|
|
36
36
|
return xstate.createActor(logic, options);
|
|
37
37
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
setActorRef(newActorRef);
|
|
46
|
-
actorRef = newActorRef;
|
|
47
|
-
}
|
|
38
|
+
// An object whose identity changes only when React Fast Refresh re-renders
|
|
39
|
+
// this component. Fast Refresh ignores dependency lists while it applies an
|
|
40
|
+
// update, so a `useMemo` with no dependencies recomputes during a refresh
|
|
41
|
+
// and at no other time.
|
|
42
|
+
const refreshSignal = React.useMemo(() => ({}), []);
|
|
43
|
+
const refreshSignalRef = React.useRef(refreshSignal);
|
|
48
44
|
|
|
45
|
+
// The logic passed on the first render is used for the hook's lifetime.
|
|
46
|
+
// Later renders only contribute implementations provided with
|
|
47
|
+
// `machine.provide()` for the same machine config.
|
|
49
48
|
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
50
49
|
useIsomorphicLayoutEffect__default["default"](() => {
|
|
51
|
-
|
|
50
|
+
const currentLogic = actorRef.logic;
|
|
51
|
+
refreshSignalRef.current !== refreshSignal;
|
|
52
|
+
refreshSignalRef.current = refreshSignal;
|
|
53
|
+
if (logic.config === currentLogic.config) {
|
|
54
|
+
currentLogic.sources = logic.sources;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
52
57
|
});
|
|
53
58
|
return [actorRef, setActorRef];
|
|
54
59
|
}
|
|
@@ -97,7 +102,7 @@ function useActorRef(machine, ...[options, observerOrListener]) {
|
|
|
97
102
|
sub.unsubscribe();
|
|
98
103
|
};
|
|
99
104
|
}, [actorRef, observerOrListener]);
|
|
100
|
-
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(
|
|
105
|
+
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(actorRef.logic, actorRef.options));
|
|
101
106
|
return actorRef;
|
|
102
107
|
}
|
|
103
108
|
|
|
@@ -213,7 +218,7 @@ function useActor(logic, ...[options]) {
|
|
|
213
218
|
if (snapshotWithStatus?.status === 'error') {
|
|
214
219
|
throw snapshotWithStatus.error;
|
|
215
220
|
}
|
|
216
|
-
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(logic, options));
|
|
221
|
+
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(actorRef.logic, options));
|
|
217
222
|
return [actorSnapshot, actorRef.send, actorRef];
|
|
218
223
|
}
|
|
219
224
|
|
|
@@ -32,23 +32,37 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
32
32
|
var useIsomorphicLayoutEffect__default = /*#__PURE__*/_interopDefault(useIsomorphicLayoutEffect);
|
|
33
33
|
|
|
34
34
|
function useIdleActorRef(logic, ...[options]) {
|
|
35
|
-
|
|
35
|
+
const [actorRef, setActorRef] = React.useState(() => {
|
|
36
36
|
return xstate.createActor(logic, options);
|
|
37
37
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
setActorRef(newActorRef);
|
|
46
|
-
actorRef = newActorRef;
|
|
47
|
-
}
|
|
38
|
+
// An object whose identity changes only when React Fast Refresh re-renders
|
|
39
|
+
// this component. Fast Refresh ignores dependency lists while it applies an
|
|
40
|
+
// update, so a `useMemo` with no dependencies recomputes during a refresh
|
|
41
|
+
// and at no other time.
|
|
42
|
+
const refreshSignal = React.useMemo(() => ({}), []);
|
|
43
|
+
const refreshSignalRef = React.useRef(refreshSignal);
|
|
48
44
|
|
|
45
|
+
// The logic passed on the first render is used for the hook's lifetime.
|
|
46
|
+
// Later renders only contribute implementations provided with
|
|
47
|
+
// `machine.provide()` for the same machine config.
|
|
49
48
|
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
50
49
|
useIsomorphicLayoutEffect__default["default"](() => {
|
|
51
|
-
|
|
50
|
+
const currentLogic = actorRef.logic;
|
|
51
|
+
const refreshed = refreshSignalRef.current !== refreshSignal;
|
|
52
|
+
refreshSignalRef.current = refreshSignal;
|
|
53
|
+
if (logic.config === currentLogic.config) {
|
|
54
|
+
currentLogic.sources = logic.sources;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Development hot reloading: Fast Refresh re-evaluated the module that
|
|
59
|
+
// defines the machine. Keep the running actor and carry its live snapshot
|
|
60
|
+
// over to the new machine; start a fresh actor if it cannot be carried.
|
|
61
|
+
if (refreshed) {
|
|
62
|
+
if (!xstate._hotSwapActorLogic(actorRef, logic)) {
|
|
63
|
+
setActorRef(xstate.createActor(logic, options));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
52
66
|
});
|
|
53
67
|
return [actorRef, setActorRef];
|
|
54
68
|
}
|
|
@@ -97,7 +111,7 @@ function useActorRef(machine, ...[options, observerOrListener]) {
|
|
|
97
111
|
sub.unsubscribe();
|
|
98
112
|
};
|
|
99
113
|
}, [actorRef, observerOrListener]);
|
|
100
|
-
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(
|
|
114
|
+
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(actorRef.logic, actorRef.options));
|
|
101
115
|
return actorRef;
|
|
102
116
|
}
|
|
103
117
|
|
|
@@ -216,7 +230,7 @@ function useActor(logic, ...[options]) {
|
|
|
216
230
|
if (snapshotWithStatus?.status === 'error') {
|
|
217
231
|
throw snapshotWithStatus.error;
|
|
218
232
|
}
|
|
219
|
-
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(logic, options));
|
|
233
|
+
useActorLifecycle(actorRef, setActorRef, () => xstate.createActor(actorRef.logic, options));
|
|
220
234
|
return [actorSnapshot, actorRef.send, actorRef];
|
|
221
235
|
}
|
|
222
236
|
|
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { useEffect, useState, useMemo, useRef, useCallback } from 'react';
|
|
3
3
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
4
|
-
import { toObserver, createActor } from 'xstate';
|
|
4
|
+
import { toObserver, createActor, _hotSwapActorLogic } from 'xstate';
|
|
5
5
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
6
6
|
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
7
|
|
|
8
8
|
function useIdleActorRef(logic, ...[options]) {
|
|
9
|
-
|
|
9
|
+
const [actorRef, setActorRef] = useState(() => {
|
|
10
10
|
return createActor(logic, options);
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
setActorRef(newActorRef);
|
|
20
|
-
actorRef = newActorRef;
|
|
21
|
-
}
|
|
12
|
+
// An object whose identity changes only when React Fast Refresh re-renders
|
|
13
|
+
// this component. Fast Refresh ignores dependency lists while it applies an
|
|
14
|
+
// update, so a `useMemo` with no dependencies recomputes during a refresh
|
|
15
|
+
// and at no other time.
|
|
16
|
+
const refreshSignal = useMemo(() => ({}), []);
|
|
17
|
+
const refreshSignalRef = useRef(refreshSignal);
|
|
22
18
|
|
|
19
|
+
// The logic passed on the first render is used for the hook's lifetime.
|
|
20
|
+
// Later renders only contribute implementations provided with
|
|
21
|
+
// `machine.provide()` for the same machine config.
|
|
23
22
|
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
24
23
|
useIsomorphicLayoutEffect(() => {
|
|
25
|
-
|
|
24
|
+
const currentLogic = actorRef.logic;
|
|
25
|
+
const refreshed = refreshSignalRef.current !== refreshSignal;
|
|
26
|
+
refreshSignalRef.current = refreshSignal;
|
|
27
|
+
if (logic.config === currentLogic.config) {
|
|
28
|
+
currentLogic.sources = logic.sources;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Development hot reloading: Fast Refresh re-evaluated the module that
|
|
33
|
+
// defines the machine. Keep the running actor and carry its live snapshot
|
|
34
|
+
// over to the new machine; start a fresh actor if it cannot be carried.
|
|
35
|
+
if (refreshed) {
|
|
36
|
+
if (!_hotSwapActorLogic(actorRef, logic)) {
|
|
37
|
+
setActorRef(createActor(logic, options));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
26
40
|
});
|
|
27
41
|
return [actorRef, setActorRef];
|
|
28
42
|
}
|
|
@@ -71,7 +85,7 @@ function useActorRef(machine, ...[options, observerOrListener]) {
|
|
|
71
85
|
sub.unsubscribe();
|
|
72
86
|
};
|
|
73
87
|
}, [actorRef, observerOrListener]);
|
|
74
|
-
useActorLifecycle(actorRef, setActorRef, () => createActor(
|
|
88
|
+
useActorLifecycle(actorRef, setActorRef, () => createActor(actorRef.logic, actorRef.options));
|
|
75
89
|
return actorRef;
|
|
76
90
|
}
|
|
77
91
|
|
|
@@ -190,7 +204,7 @@ function useActor(logic, ...[options]) {
|
|
|
190
204
|
if (snapshotWithStatus?.status === 'error') {
|
|
191
205
|
throw snapshotWithStatus.error;
|
|
192
206
|
}
|
|
193
|
-
useActorLifecycle(actorRef, setActorRef, () => createActor(logic, options));
|
|
207
|
+
useActorLifecycle(actorRef, setActorRef, () => createActor(actorRef.logic, options));
|
|
194
208
|
return [actorSnapshot, actorRef.send, actorRef];
|
|
195
209
|
}
|
|
196
210
|
|
package/dist/xstate-react.esm.js
CHANGED
|
@@ -1,28 +1,33 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { useEffect, useState, useMemo, useRef, useCallback } from 'react';
|
|
3
3
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
4
4
|
import { toObserver, createActor } from 'xstate';
|
|
5
5
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
6
6
|
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
7
|
|
|
8
8
|
function useIdleActorRef(logic, ...[options]) {
|
|
9
|
-
|
|
9
|
+
const [actorRef, setActorRef] = useState(() => {
|
|
10
10
|
return createActor(logic, options);
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
setActorRef(newActorRef);
|
|
20
|
-
actorRef = newActorRef;
|
|
21
|
-
}
|
|
12
|
+
// An object whose identity changes only when React Fast Refresh re-renders
|
|
13
|
+
// this component. Fast Refresh ignores dependency lists while it applies an
|
|
14
|
+
// update, so a `useMemo` with no dependencies recomputes during a refresh
|
|
15
|
+
// and at no other time.
|
|
16
|
+
const refreshSignal = useMemo(() => ({}), []);
|
|
17
|
+
const refreshSignalRef = useRef(refreshSignal);
|
|
22
18
|
|
|
19
|
+
// The logic passed on the first render is used for the hook's lifetime.
|
|
20
|
+
// Later renders only contribute implementations provided with
|
|
21
|
+
// `machine.provide()` for the same machine config.
|
|
23
22
|
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
24
23
|
useIsomorphicLayoutEffect(() => {
|
|
25
|
-
|
|
24
|
+
const currentLogic = actorRef.logic;
|
|
25
|
+
refreshSignalRef.current !== refreshSignal;
|
|
26
|
+
refreshSignalRef.current = refreshSignal;
|
|
27
|
+
if (logic.config === currentLogic.config) {
|
|
28
|
+
currentLogic.sources = logic.sources;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
26
31
|
});
|
|
27
32
|
return [actorRef, setActorRef];
|
|
28
33
|
}
|
|
@@ -71,7 +76,7 @@ function useActorRef(machine, ...[options, observerOrListener]) {
|
|
|
71
76
|
sub.unsubscribe();
|
|
72
77
|
};
|
|
73
78
|
}, [actorRef, observerOrListener]);
|
|
74
|
-
useActorLifecycle(actorRef, setActorRef, () => createActor(
|
|
79
|
+
useActorLifecycle(actorRef, setActorRef, () => createActor(actorRef.logic, actorRef.options));
|
|
75
80
|
return actorRef;
|
|
76
81
|
}
|
|
77
82
|
|
|
@@ -187,7 +192,7 @@ function useActor(logic, ...[options]) {
|
|
|
187
192
|
if (snapshotWithStatus?.status === 'error') {
|
|
188
193
|
throw snapshotWithStatus.error;
|
|
189
194
|
}
|
|
190
|
-
useActorLifecycle(actorRef, setActorRef, () => createActor(logic, options));
|
|
195
|
+
useActorLifecycle(actorRef, setActorRef, () => createActor(actorRef.logic, options));
|
|
191
196
|
return [actorSnapshot, actorRef.send, actorRef];
|
|
192
197
|
}
|
|
193
198
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xstate/react",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.4",
|
|
4
4
|
"description": "XState tools for React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
57
|
-
"xstate": "^6.0.0-alpha.
|
|
57
|
+
"xstate": "^6.0.0-alpha.61"
|
|
58
58
|
},
|
|
59
59
|
"peerDependenciesMeta": {
|
|
60
60
|
"xstate": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"react-dom": "^19.0.0",
|
|
75
75
|
"rxjs": "^7.8.1",
|
|
76
76
|
"zod": "^3.25.51",
|
|
77
|
-
"xstate": "^6.0.0-alpha.
|
|
77
|
+
"xstate": "^6.0.0-alpha.61"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {}
|
|
80
80
|
}
|