@xstate/react 4.1.0 → 4.1.2
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 +3 -3
- package/dist/declarations/src/createActorContext.d.ts +1 -3
- package/dist/declarations/src/index.d.ts +2 -2
- package/dist/declarations/src/useActor.d.ts +6 -2
- package/dist/declarations/src/useActorRef.d.ts +15 -3
- package/dist/declarations/src/useMachine.d.ts +7 -5
- package/dist/declarations/src/useSelector.d.ts +4 -2
- package/dist/xstate-react.cjs.js +50 -52
- package/dist/xstate-react.development.cjs.js +53 -55
- package/dist/xstate-react.development.esm.js +53 -55
- package/dist/xstate-react.esm.js +50 -52
- package/package.json +8 -10
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This package contains utilities for using [XState](https://github.com/statelyai/xstate) with [React](https://github.com/facebook/react/).
|
|
4
4
|
|
|
5
|
-
- [Read the full documentation in the XState docs](https://
|
|
5
|
+
- [Read the full documentation in the XState docs](https://stately.ai/docs/xstate-react).
|
|
6
6
|
- [Read our contribution guidelines](https://github.com/statelyai/xstate/blob/main/CONTRIBUTING.md).
|
|
7
7
|
|
|
8
8
|
## Quick start
|
|
@@ -15,7 +15,7 @@ npm i xstate @xstate/react
|
|
|
15
15
|
|
|
16
16
|
2. Import the `useMachine` hook:
|
|
17
17
|
|
|
18
|
-
```
|
|
18
|
+
```tsx
|
|
19
19
|
import { useMachine } from '@xstate/react';
|
|
20
20
|
import { createMachine } from 'xstate';
|
|
21
21
|
|
|
@@ -36,7 +36,7 @@ export const Toggler = () => {
|
|
|
36
36
|
const [state, send] = useMachine(toggleMachine);
|
|
37
37
|
|
|
38
38
|
return (
|
|
39
|
-
<button onClick={() => send('TOGGLE')}>
|
|
39
|
+
<button onClick={() => send({ type: 'TOGGLE' })}>
|
|
40
40
|
{state.value === 'inactive'
|
|
41
41
|
? 'Click to activate'
|
|
42
42
|
: 'Active! Click to deactivate'}
|
|
@@ -6,9 +6,7 @@ export declare function createActorContext<TLogic extends AnyActorLogic>(actorLo
|
|
|
6
6
|
Provider: (props: {
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
options?: ActorOptions<TLogic>;
|
|
9
|
-
/**
|
|
10
|
-
* @deprecated Use `logic` instead.
|
|
11
|
-
*/
|
|
9
|
+
/** @deprecated Use `logic` instead. */
|
|
12
10
|
machine?: never;
|
|
13
11
|
logic?: TLogic;
|
|
14
12
|
}) => React.ReactElement<any, any>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
export { createActorContext } from "./createActorContext.js";
|
|
2
|
+
export { shallowEqual } from "./shallowEqual.js";
|
|
1
3
|
export { useActor } from "./useActor.js";
|
|
2
4
|
export { useActorRef } from "./useActorRef.js";
|
|
3
5
|
export { useSelector } from "./useSelector.js";
|
|
4
|
-
export { shallowEqual } from "./shallowEqual.js";
|
|
5
|
-
export { createActorContext } from "./createActorContext.js";
|
|
6
6
|
export { useMachine } from "./useMachine.js";
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyActorLogic, SnapshotFrom } from 'xstate';
|
|
2
|
-
export declare function useActor<TLogic extends AnyActorLogic>(logic: TLogic, options
|
|
1
|
+
import { Actor, ActorOptions, AnyActorLogic, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
2
|
+
export declare function useActor<TLogic extends AnyActorLogic>(logic: TLogic, ...[options]: ConditionalRequired<[
|
|
3
|
+
options?: ActorOptions<TLogic> & {
|
|
4
|
+
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
5
|
+
}
|
|
6
|
+
], IsNotNever<RequiredActorOptionsKeys<TLogic>>>): [SnapshotFrom<TLogic>, Actor<TLogic>['send'], Actor<TLogic>];
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyActorLogic, Observer, SnapshotFrom } from 'xstate';
|
|
2
|
-
export declare function useIdleActorRef<TLogic extends AnyActorLogic>(logic: TLogic, options:
|
|
3
|
-
|
|
1
|
+
import { Actor, ActorOptions, AnyActorLogic, Observer, SnapshotFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
2
|
+
export declare function useIdleActorRef<TLogic extends AnyActorLogic>(logic: TLogic, ...[options]: ConditionalRequired<[
|
|
3
|
+
options?: ActorOptions<TLogic> & {
|
|
4
|
+
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
5
|
+
}
|
|
6
|
+
], IsNotNever<RequiredActorOptionsKeys<TLogic>>>): Actor<TLogic>;
|
|
7
|
+
export declare function useActorRef<TLogic extends AnyActorLogic>(machine: TLogic, ...[options, observerOrListener]: IsNotNever<RequiredActorOptionsKeys<TLogic>> extends true ? [
|
|
8
|
+
options: ActorOptions<TLogic> & {
|
|
9
|
+
[K in RequiredActorOptionsKeys<TLogic>]: unknown;
|
|
10
|
+
},
|
|
11
|
+
observerOrListener?: Observer<SnapshotFrom<TLogic>> | ((value: SnapshotFrom<TLogic>) => void)
|
|
12
|
+
] : [
|
|
13
|
+
options?: ActorOptions<TLogic>,
|
|
14
|
+
observerOrListener?: Observer<SnapshotFrom<TLogic>> | ((value: SnapshotFrom<TLogic>) => void)
|
|
15
|
+
]): Actor<TLogic>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { Actor, ActorOptions, AnyStateMachine, StateFrom } from 'xstate';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Actor, ActorOptions, AnyStateMachine, StateFrom, type ConditionalRequired, type IsNotNever, type RequiredActorOptionsKeys } from 'xstate';
|
|
2
|
+
/** @alias useActor */
|
|
3
|
+
export declare function useMachine<TMachine extends AnyStateMachine>(machine: TMachine, ...[options]: ConditionalRequired<[
|
|
4
|
+
options?: ActorOptions<TMachine> & {
|
|
5
|
+
[K in RequiredActorOptionsKeys<TMachine>]: unknown;
|
|
6
|
+
}
|
|
7
|
+
], IsNotNever<RequiredActorOptionsKeys<TMachine>>>): [StateFrom<TMachine>, Actor<TMachine>['send'], Actor<TMachine>];
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function useSelector<TActor extends
|
|
1
|
+
import { AnyActorRef } from 'xstate';
|
|
2
|
+
export declare function useSelector<TActor extends Pick<AnyActorRef, 'subscribe' | 'getSnapshot'> | undefined, T>(actor: TActor, selector: (snapshot: TActor extends {
|
|
3
|
+
getSnapshot(): infer TSnapshot;
|
|
4
|
+
} ? TSnapshot : undefined) => T, compare?: (a: T, b: T) => boolean): T;
|
package/dist/xstate-react.cjs.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var shim = require('use-sync-external-store/shim');
|
|
7
6
|
var useIsomorphicLayoutEffect = require('use-isomorphic-layout-effect');
|
|
8
7
|
var xstate = require('xstate');
|
|
9
8
|
var withSelector = require('use-sync-external-store/shim/with-selector');
|
|
9
|
+
var shim = require('use-sync-external-store/shim');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
12
12
|
|
|
@@ -63,7 +63,7 @@ function stopRootWithRehydration(actorRef) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function useIdleActorRef(logic, options) {
|
|
66
|
+
function useIdleActorRef(logic, ...[options]) {
|
|
67
67
|
let [[currentConfig, actorRef], setCurrent] = React.useState(() => {
|
|
68
68
|
const actorRef = xstate.createActor(logic, options);
|
|
69
69
|
return [logic.config, actorRef];
|
|
@@ -85,7 +85,7 @@ function useIdleActorRef(logic, options) {
|
|
|
85
85
|
});
|
|
86
86
|
return actorRef;
|
|
87
87
|
}
|
|
88
|
-
function useActorRef(machine, options
|
|
88
|
+
function useActorRef(machine, ...[options, observerOrListener]) {
|
|
89
89
|
const actorRef = useIdleActorRef(machine, options);
|
|
90
90
|
React.useEffect(() => {
|
|
91
91
|
if (!observerOrListener) {
|
|
@@ -105,27 +105,6 @@ function useActorRef(machine, options = {}, observerOrListener) {
|
|
|
105
105
|
return actorRef;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function useActor(logic, options = {}) {
|
|
109
|
-
const actorRef = useIdleActorRef(logic, options);
|
|
110
|
-
const getSnapshot = React.useCallback(() => {
|
|
111
|
-
return actorRef.getSnapshot();
|
|
112
|
-
}, [actorRef]);
|
|
113
|
-
const subscribe = React.useCallback(handleStoreChange => {
|
|
114
|
-
const {
|
|
115
|
-
unsubscribe
|
|
116
|
-
} = actorRef.subscribe(handleStoreChange);
|
|
117
|
-
return unsubscribe;
|
|
118
|
-
}, [actorRef]);
|
|
119
|
-
const actorSnapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
120
|
-
React.useEffect(() => {
|
|
121
|
-
actorRef.start();
|
|
122
|
-
return () => {
|
|
123
|
-
stopRootWithRehydration(actorRef);
|
|
124
|
-
};
|
|
125
|
-
}, [actorRef]);
|
|
126
|
-
return [actorSnapshot, actorRef.send, actorRef];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
108
|
function defaultCompare(a, b) {
|
|
130
109
|
return a === b;
|
|
131
110
|
}
|
|
@@ -144,30 +123,6 @@ function useSelector(actor, selector, compare = defaultCompare) {
|
|
|
144
123
|
return selectedSnapshot;
|
|
145
124
|
}
|
|
146
125
|
|
|
147
|
-
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
148
|
-
function is(x, y) {
|
|
149
|
-
if (x === y) {
|
|
150
|
-
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
151
|
-
} else {
|
|
152
|
-
return x !== x && y !== y;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function shallowEqual(objA, objB) {
|
|
156
|
-
if (is(objA, objB)) return true;
|
|
157
|
-
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
const keysA = Object.keys(objA);
|
|
161
|
-
const keysB = Object.keys(objB);
|
|
162
|
-
if (keysA.length !== keysB.length) return false;
|
|
163
|
-
for (let i = 0; i < keysA.length; i++) {
|
|
164
|
-
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
126
|
function createActorContext(actorLogic, actorOptions) {
|
|
172
127
|
const ReactContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
173
128
|
const OriginalProvider = ReactContext.Provider;
|
|
@@ -210,10 +165,53 @@ function createActorContext(actorLogic, actorOptions) {
|
|
|
210
165
|
};
|
|
211
166
|
}
|
|
212
167
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
168
|
+
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
169
|
+
function is(x, y) {
|
|
170
|
+
if (x === y) {
|
|
171
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
172
|
+
} else {
|
|
173
|
+
return x !== x && y !== y;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function shallowEqual(objA, objB) {
|
|
177
|
+
if (is(objA, objB)) return true;
|
|
178
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const keysA = Object.keys(objA);
|
|
182
|
+
const keysB = Object.keys(objB);
|
|
183
|
+
if (keysA.length !== keysB.length) return false;
|
|
184
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
185
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function useActor(logic, ...[options]) {
|
|
193
|
+
const actorRef = useIdleActorRef(logic, options);
|
|
194
|
+
const getSnapshot = React.useCallback(() => {
|
|
195
|
+
return actorRef.getSnapshot();
|
|
196
|
+
}, [actorRef]);
|
|
197
|
+
const subscribe = React.useCallback(handleStoreChange => {
|
|
198
|
+
const {
|
|
199
|
+
unsubscribe
|
|
200
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
201
|
+
return unsubscribe;
|
|
202
|
+
}, [actorRef]);
|
|
203
|
+
const actorSnapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
204
|
+
React.useEffect(() => {
|
|
205
|
+
actorRef.start();
|
|
206
|
+
return () => {
|
|
207
|
+
stopRootWithRehydration(actorRef);
|
|
208
|
+
};
|
|
209
|
+
}, [actorRef]);
|
|
210
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** @alias useActor */
|
|
214
|
+
function useMachine(machine, ...[options]) {
|
|
217
215
|
return useActor(machine, options);
|
|
218
216
|
}
|
|
219
217
|
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var shim = require('use-sync-external-store/shim');
|
|
7
6
|
var useIsomorphicLayoutEffect = require('use-isomorphic-layout-effect');
|
|
8
7
|
var xstate = require('xstate');
|
|
9
8
|
var withSelector = require('use-sync-external-store/shim/with-selector');
|
|
9
|
+
var shim = require('use-sync-external-store/shim');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
12
12
|
|
|
@@ -63,7 +63,7 @@ function stopRootWithRehydration(actorRef) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function useIdleActorRef(logic, options) {
|
|
66
|
+
function useIdleActorRef(logic, ...[options]) {
|
|
67
67
|
let [[currentConfig, actorRef], setCurrent] = React.useState(() => {
|
|
68
68
|
const actorRef = xstate.createActor(logic, options);
|
|
69
69
|
return [logic.config, actorRef];
|
|
@@ -85,7 +85,7 @@ function useIdleActorRef(logic, options) {
|
|
|
85
85
|
});
|
|
86
86
|
return actorRef;
|
|
87
87
|
}
|
|
88
|
-
function useActorRef(machine, options
|
|
88
|
+
function useActorRef(machine, ...[options, observerOrListener]) {
|
|
89
89
|
const actorRef = useIdleActorRef(machine, options);
|
|
90
90
|
React.useEffect(() => {
|
|
91
91
|
if (!observerOrListener) {
|
|
@@ -105,30 +105,6 @@ function useActorRef(machine, options = {}, observerOrListener) {
|
|
|
105
105
|
return actorRef;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function useActor(logic, options = {}) {
|
|
109
|
-
if (!!logic && 'send' in logic && typeof logic.send === 'function') {
|
|
110
|
-
throw new Error(`useActor() expects actor logic (e.g. a machine), but received an ActorRef. Use the useSelector(actorRef, ...) hook instead to read the ActorRef's snapshot.`);
|
|
111
|
-
}
|
|
112
|
-
const actorRef = useIdleActorRef(logic, options);
|
|
113
|
-
const getSnapshot = React.useCallback(() => {
|
|
114
|
-
return actorRef.getSnapshot();
|
|
115
|
-
}, [actorRef]);
|
|
116
|
-
const subscribe = React.useCallback(handleStoreChange => {
|
|
117
|
-
const {
|
|
118
|
-
unsubscribe
|
|
119
|
-
} = actorRef.subscribe(handleStoreChange);
|
|
120
|
-
return unsubscribe;
|
|
121
|
-
}, [actorRef]);
|
|
122
|
-
const actorSnapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
123
|
-
React.useEffect(() => {
|
|
124
|
-
actorRef.start();
|
|
125
|
-
return () => {
|
|
126
|
-
stopRootWithRehydration(actorRef);
|
|
127
|
-
};
|
|
128
|
-
}, [actorRef]);
|
|
129
|
-
return [actorSnapshot, actorRef.send, actorRef];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
108
|
function defaultCompare(a, b) {
|
|
133
109
|
return a === b;
|
|
134
110
|
}
|
|
@@ -147,30 +123,6 @@ function useSelector(actor, selector, compare = defaultCompare) {
|
|
|
147
123
|
return selectedSnapshot;
|
|
148
124
|
}
|
|
149
125
|
|
|
150
|
-
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
151
|
-
function is(x, y) {
|
|
152
|
-
if (x === y) {
|
|
153
|
-
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
154
|
-
} else {
|
|
155
|
-
return x !== x && y !== y;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
function shallowEqual(objA, objB) {
|
|
159
|
-
if (is(objA, objB)) return true;
|
|
160
|
-
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
const keysA = Object.keys(objA);
|
|
164
|
-
const keysB = Object.keys(objB);
|
|
165
|
-
if (keysA.length !== keysB.length) return false;
|
|
166
|
-
for (let i = 0; i < keysA.length; i++) {
|
|
167
|
-
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
126
|
function createActorContext(actorLogic, actorOptions) {
|
|
175
127
|
const ReactContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
176
128
|
const OriginalProvider = ReactContext.Provider;
|
|
@@ -213,10 +165,56 @@ function createActorContext(actorLogic, actorOptions) {
|
|
|
213
165
|
};
|
|
214
166
|
}
|
|
215
167
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
168
|
+
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
169
|
+
function is(x, y) {
|
|
170
|
+
if (x === y) {
|
|
171
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
172
|
+
} else {
|
|
173
|
+
return x !== x && y !== y;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function shallowEqual(objA, objB) {
|
|
177
|
+
if (is(objA, objB)) return true;
|
|
178
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const keysA = Object.keys(objA);
|
|
182
|
+
const keysB = Object.keys(objB);
|
|
183
|
+
if (keysA.length !== keysB.length) return false;
|
|
184
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
185
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function useActor(logic, ...[options]) {
|
|
193
|
+
if (!!logic && 'send' in logic && typeof logic.send === 'function') {
|
|
194
|
+
throw new Error(`useActor() expects actor logic (e.g. a machine), but received an ActorRef. Use the useSelector(actorRef, ...) hook instead to read the ActorRef's snapshot.`);
|
|
195
|
+
}
|
|
196
|
+
const actorRef = useIdleActorRef(logic, options);
|
|
197
|
+
const getSnapshot = React.useCallback(() => {
|
|
198
|
+
return actorRef.getSnapshot();
|
|
199
|
+
}, [actorRef]);
|
|
200
|
+
const subscribe = React.useCallback(handleStoreChange => {
|
|
201
|
+
const {
|
|
202
|
+
unsubscribe
|
|
203
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
204
|
+
return unsubscribe;
|
|
205
|
+
}, [actorRef]);
|
|
206
|
+
const actorSnapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
207
|
+
React.useEffect(() => {
|
|
208
|
+
actorRef.start();
|
|
209
|
+
return () => {
|
|
210
|
+
stopRootWithRehydration(actorRef);
|
|
211
|
+
};
|
|
212
|
+
}, [actorRef]);
|
|
213
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** @alias useActor */
|
|
217
|
+
function useMachine(machine, ...[options]) {
|
|
220
218
|
return useActor(machine, options);
|
|
221
219
|
}
|
|
222
220
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useEffect, useState, useCallback } from 'react';
|
|
3
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
4
3
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
5
4
|
import { toObserver, createActor } from 'xstate';
|
|
6
5
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
6
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
7
|
|
|
8
8
|
const forEachActor = (actorRef, callback) => {
|
|
9
9
|
callback(actorRef);
|
|
@@ -37,7 +37,7 @@ function stopRootWithRehydration(actorRef) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function useIdleActorRef(logic, options) {
|
|
40
|
+
function useIdleActorRef(logic, ...[options]) {
|
|
41
41
|
let [[currentConfig, actorRef], setCurrent] = useState(() => {
|
|
42
42
|
const actorRef = createActor(logic, options);
|
|
43
43
|
return [logic.config, actorRef];
|
|
@@ -59,7 +59,7 @@ function useIdleActorRef(logic, options) {
|
|
|
59
59
|
});
|
|
60
60
|
return actorRef;
|
|
61
61
|
}
|
|
62
|
-
function useActorRef(machine, options
|
|
62
|
+
function useActorRef(machine, ...[options, observerOrListener]) {
|
|
63
63
|
const actorRef = useIdleActorRef(machine, options);
|
|
64
64
|
useEffect(() => {
|
|
65
65
|
if (!observerOrListener) {
|
|
@@ -79,30 +79,6 @@ function useActorRef(machine, options = {}, observerOrListener) {
|
|
|
79
79
|
return actorRef;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
function useActor(logic, options = {}) {
|
|
83
|
-
if (!!logic && 'send' in logic && typeof logic.send === 'function') {
|
|
84
|
-
throw new Error(`useActor() expects actor logic (e.g. a machine), but received an ActorRef. Use the useSelector(actorRef, ...) hook instead to read the ActorRef's snapshot.`);
|
|
85
|
-
}
|
|
86
|
-
const actorRef = useIdleActorRef(logic, options);
|
|
87
|
-
const getSnapshot = useCallback(() => {
|
|
88
|
-
return actorRef.getSnapshot();
|
|
89
|
-
}, [actorRef]);
|
|
90
|
-
const subscribe = useCallback(handleStoreChange => {
|
|
91
|
-
const {
|
|
92
|
-
unsubscribe
|
|
93
|
-
} = actorRef.subscribe(handleStoreChange);
|
|
94
|
-
return unsubscribe;
|
|
95
|
-
}, [actorRef]);
|
|
96
|
-
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
actorRef.start();
|
|
99
|
-
return () => {
|
|
100
|
-
stopRootWithRehydration(actorRef);
|
|
101
|
-
};
|
|
102
|
-
}, [actorRef]);
|
|
103
|
-
return [actorSnapshot, actorRef.send, actorRef];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
82
|
function defaultCompare(a, b) {
|
|
107
83
|
return a === b;
|
|
108
84
|
}
|
|
@@ -121,30 +97,6 @@ function useSelector(actor, selector, compare = defaultCompare) {
|
|
|
121
97
|
return selectedSnapshot;
|
|
122
98
|
}
|
|
123
99
|
|
|
124
|
-
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
125
|
-
function is(x, y) {
|
|
126
|
-
if (x === y) {
|
|
127
|
-
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
128
|
-
} else {
|
|
129
|
-
return x !== x && y !== y;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function shallowEqual(objA, objB) {
|
|
133
|
-
if (is(objA, objB)) return true;
|
|
134
|
-
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
const keysA = Object.keys(objA);
|
|
138
|
-
const keysB = Object.keys(objB);
|
|
139
|
-
if (keysA.length !== keysB.length) return false;
|
|
140
|
-
for (let i = 0; i < keysA.length; i++) {
|
|
141
|
-
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
100
|
function createActorContext(actorLogic, actorOptions) {
|
|
149
101
|
const ReactContext = /*#__PURE__*/React.createContext(null);
|
|
150
102
|
const OriginalProvider = ReactContext.Provider;
|
|
@@ -187,10 +139,56 @@ function createActorContext(actorLogic, actorOptions) {
|
|
|
187
139
|
};
|
|
188
140
|
}
|
|
189
141
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
142
|
+
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
143
|
+
function is(x, y) {
|
|
144
|
+
if (x === y) {
|
|
145
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
146
|
+
} else {
|
|
147
|
+
return x !== x && y !== y;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function shallowEqual(objA, objB) {
|
|
151
|
+
if (is(objA, objB)) return true;
|
|
152
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const keysA = Object.keys(objA);
|
|
156
|
+
const keysB = Object.keys(objB);
|
|
157
|
+
if (keysA.length !== keysB.length) return false;
|
|
158
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
159
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function useActor(logic, ...[options]) {
|
|
167
|
+
if (!!logic && 'send' in logic && typeof logic.send === 'function') {
|
|
168
|
+
throw new Error(`useActor() expects actor logic (e.g. a machine), but received an ActorRef. Use the useSelector(actorRef, ...) hook instead to read the ActorRef's snapshot.`);
|
|
169
|
+
}
|
|
170
|
+
const actorRef = useIdleActorRef(logic, options);
|
|
171
|
+
const getSnapshot = useCallback(() => {
|
|
172
|
+
return actorRef.getSnapshot();
|
|
173
|
+
}, [actorRef]);
|
|
174
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
175
|
+
const {
|
|
176
|
+
unsubscribe
|
|
177
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
178
|
+
return unsubscribe;
|
|
179
|
+
}, [actorRef]);
|
|
180
|
+
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
actorRef.start();
|
|
183
|
+
return () => {
|
|
184
|
+
stopRootWithRehydration(actorRef);
|
|
185
|
+
};
|
|
186
|
+
}, [actorRef]);
|
|
187
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** @alias useActor */
|
|
191
|
+
function useMachine(machine, ...[options]) {
|
|
194
192
|
return useActor(machine, options);
|
|
195
193
|
}
|
|
196
194
|
|
package/dist/xstate-react.esm.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useEffect, useState, useCallback } from 'react';
|
|
3
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
4
3
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
5
4
|
import { toObserver, createActor } from 'xstate';
|
|
6
5
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
6
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
7
|
|
|
8
8
|
const forEachActor = (actorRef, callback) => {
|
|
9
9
|
callback(actorRef);
|
|
@@ -37,7 +37,7 @@ function stopRootWithRehydration(actorRef) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function useIdleActorRef(logic, options) {
|
|
40
|
+
function useIdleActorRef(logic, ...[options]) {
|
|
41
41
|
let [[currentConfig, actorRef], setCurrent] = useState(() => {
|
|
42
42
|
const actorRef = createActor(logic, options);
|
|
43
43
|
return [logic.config, actorRef];
|
|
@@ -59,7 +59,7 @@ function useIdleActorRef(logic, options) {
|
|
|
59
59
|
});
|
|
60
60
|
return actorRef;
|
|
61
61
|
}
|
|
62
|
-
function useActorRef(machine, options
|
|
62
|
+
function useActorRef(machine, ...[options, observerOrListener]) {
|
|
63
63
|
const actorRef = useIdleActorRef(machine, options);
|
|
64
64
|
useEffect(() => {
|
|
65
65
|
if (!observerOrListener) {
|
|
@@ -79,27 +79,6 @@ function useActorRef(machine, options = {}, observerOrListener) {
|
|
|
79
79
|
return actorRef;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
function useActor(logic, options = {}) {
|
|
83
|
-
const actorRef = useIdleActorRef(logic, options);
|
|
84
|
-
const getSnapshot = useCallback(() => {
|
|
85
|
-
return actorRef.getSnapshot();
|
|
86
|
-
}, [actorRef]);
|
|
87
|
-
const subscribe = useCallback(handleStoreChange => {
|
|
88
|
-
const {
|
|
89
|
-
unsubscribe
|
|
90
|
-
} = actorRef.subscribe(handleStoreChange);
|
|
91
|
-
return unsubscribe;
|
|
92
|
-
}, [actorRef]);
|
|
93
|
-
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
actorRef.start();
|
|
96
|
-
return () => {
|
|
97
|
-
stopRootWithRehydration(actorRef);
|
|
98
|
-
};
|
|
99
|
-
}, [actorRef]);
|
|
100
|
-
return [actorSnapshot, actorRef.send, actorRef];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
82
|
function defaultCompare(a, b) {
|
|
104
83
|
return a === b;
|
|
105
84
|
}
|
|
@@ -118,30 +97,6 @@ function useSelector(actor, selector, compare = defaultCompare) {
|
|
|
118
97
|
return selectedSnapshot;
|
|
119
98
|
}
|
|
120
99
|
|
|
121
|
-
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
122
|
-
function is(x, y) {
|
|
123
|
-
if (x === y) {
|
|
124
|
-
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
125
|
-
} else {
|
|
126
|
-
return x !== x && y !== y;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
function shallowEqual(objA, objB) {
|
|
130
|
-
if (is(objA, objB)) return true;
|
|
131
|
-
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
const keysA = Object.keys(objA);
|
|
135
|
-
const keysB = Object.keys(objB);
|
|
136
|
-
if (keysA.length !== keysB.length) return false;
|
|
137
|
-
for (let i = 0; i < keysA.length; i++) {
|
|
138
|
-
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return true;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
100
|
function createActorContext(actorLogic, actorOptions) {
|
|
146
101
|
const ReactContext = /*#__PURE__*/React.createContext(null);
|
|
147
102
|
const OriginalProvider = ReactContext.Provider;
|
|
@@ -184,10 +139,53 @@ function createActorContext(actorLogic, actorOptions) {
|
|
|
184
139
|
};
|
|
185
140
|
}
|
|
186
141
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
142
|
+
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
143
|
+
function is(x, y) {
|
|
144
|
+
if (x === y) {
|
|
145
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
146
|
+
} else {
|
|
147
|
+
return x !== x && y !== y;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function shallowEqual(objA, objB) {
|
|
151
|
+
if (is(objA, objB)) return true;
|
|
152
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const keysA = Object.keys(objA);
|
|
156
|
+
const keysB = Object.keys(objB);
|
|
157
|
+
if (keysA.length !== keysB.length) return false;
|
|
158
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
159
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function useActor(logic, ...[options]) {
|
|
167
|
+
const actorRef = useIdleActorRef(logic, options);
|
|
168
|
+
const getSnapshot = useCallback(() => {
|
|
169
|
+
return actorRef.getSnapshot();
|
|
170
|
+
}, [actorRef]);
|
|
171
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
172
|
+
const {
|
|
173
|
+
unsubscribe
|
|
174
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
175
|
+
return unsubscribe;
|
|
176
|
+
}, [actorRef]);
|
|
177
|
+
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
actorRef.start();
|
|
180
|
+
return () => {
|
|
181
|
+
stopRootWithRehydration(actorRef);
|
|
182
|
+
};
|
|
183
|
+
}, [actorRef]);
|
|
184
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** @alias useActor */
|
|
188
|
+
function useMachine(machine, ...[options]) {
|
|
191
189
|
return useActor(machine, options);
|
|
192
190
|
}
|
|
193
191
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xstate/react",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"description": "XState tools for React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
58
|
-
"xstate": "^5.
|
|
58
|
+
"xstate": "^5.18.1"
|
|
59
59
|
},
|
|
60
60
|
"peerDependenciesMeta": {
|
|
61
61
|
"xstate": {
|
|
@@ -64,18 +64,16 @@
|
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"use-isomorphic-layout-effect": "^1.1.2",
|
|
67
|
-
"use-sync-external-store": "^1.
|
|
67
|
+
"use-sync-external-store": "^1.2.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@testing-library/react": "^
|
|
71
|
-
"@types/
|
|
72
|
-
"@types/react": "^
|
|
73
|
-
"@types/react-dom": "^17.0.14",
|
|
70
|
+
"@testing-library/react": "^16.0.0",
|
|
71
|
+
"@types/react": "^18.3.3",
|
|
72
|
+
"@types/react-dom": "^18.3.0",
|
|
74
73
|
"@types/use-sync-external-store": "^0.0.3",
|
|
75
|
-
"jsdom": "^14.0.0",
|
|
76
|
-
"jsdom-global": "^3.0.2",
|
|
77
74
|
"react": "^18.0.0",
|
|
78
75
|
"react-dom": "^18.0.0",
|
|
79
|
-
"
|
|
76
|
+
"rxjs": "^7.8.0",
|
|
77
|
+
"xstate": "5.18.1"
|
|
80
78
|
}
|
|
81
79
|
}
|