@xstate/react 4.0.0-alpha.1 → 4.0.0-beta.10
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 +0 -8
- package/dist/declarations/src/createActorContext.d.ts +18 -0
- package/dist/declarations/src/index.d.ts +6 -6
- package/dist/declarations/src/useActor.d.ts +2 -3
- package/dist/declarations/src/useActorRef.d.ts +14 -0
- package/dist/declarations/src/useMachine.d.ts +8 -20
- package/dist/xstate-react.cjs.d.mts +2 -0
- package/dist/xstate-react.cjs.d.mts.map +1 -0
- package/dist/xstate-react.cjs.d.ts +1 -0
- package/dist/xstate-react.cjs.d.ts.map +1 -0
- package/dist/xstate-react.cjs.js +187 -4
- package/dist/xstate-react.cjs.mjs +8 -0
- package/dist/xstate-react.development.cjs.js +199 -0
- package/dist/xstate-react.development.cjs.mjs +8 -0
- package/dist/xstate-react.development.esm.js +168 -0
- package/dist/xstate-react.esm.js +107 -226
- package/package.json +22 -22
- package/dist/declarations/src/fsm.d.ts +0 -3
- package/dist/declarations/src/types.d.ts +0 -15
- package/dist/declarations/src/useConstant.d.ts +0 -1
- package/dist/declarations/src/useInterpret.d.ts +0 -13
- package/dist/declarations/src/useSpawn.d.ts +0 -9
- package/dist/useConstant-644f0e11.cjs.dev.js +0 -74
- package/dist/useConstant-94bfdbb5.esm.js +0 -71
- package/dist/useConstant-eeb49d3f.cjs.prod.js +0 -17
- package/dist/xstate-react.cjs.dev.js +0 -291
- package/dist/xstate-react.cjs.prod.js +0 -281
- package/fsm/dist/xstate-react-fsm.cjs.d.ts +0 -1
- package/fsm/dist/xstate-react-fsm.cjs.dev.js +0 -98
- package/fsm/dist/xstate-react-fsm.cjs.js +0 -7
- package/fsm/dist/xstate-react-fsm.cjs.prod.js +0 -144
- package/fsm/dist/xstate-react-fsm.esm.js +0 -89
- package/fsm/package.json +0 -4
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
3
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
4
|
+
import { toObserver, ActorStatus, createActor } from 'xstate';
|
|
5
|
+
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
6
|
+
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
7
|
+
|
|
8
|
+
function useConstant(fn) {
|
|
9
|
+
const ref = React.useRef();
|
|
10
|
+
if (!ref.current) {
|
|
11
|
+
ref.current = {
|
|
12
|
+
v: fn()
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return ref.current.v;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function useIdleInterpreter(machine, options) {
|
|
19
|
+
{
|
|
20
|
+
const [initialMachine] = useState(machine);
|
|
21
|
+
if (machine.config !== initialMachine.config) {
|
|
22
|
+
console.warn(`Actor logic has changed between renders. This is not supported and may lead to invalid snapshots.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const actorRef = useConstant(() => {
|
|
26
|
+
return createActor(machine, options);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
30
|
+
useIsomorphicLayoutEffect(() => {
|
|
31
|
+
actorRef.logic.implementations = machine.implementations;
|
|
32
|
+
});
|
|
33
|
+
return actorRef;
|
|
34
|
+
}
|
|
35
|
+
function useActorRef(machine, ...[options = {}, observerOrListener]) {
|
|
36
|
+
const actorRef = useIdleInterpreter(machine, options);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!observerOrListener) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let sub = actorRef.subscribe(toObserver(observerOrListener));
|
|
42
|
+
return () => {
|
|
43
|
+
sub.unsubscribe();
|
|
44
|
+
};
|
|
45
|
+
}, [observerOrListener]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
actorRef.start();
|
|
48
|
+
return () => {
|
|
49
|
+
actorRef.stop();
|
|
50
|
+
actorRef.status = ActorStatus.NotStarted;
|
|
51
|
+
actorRef._initState();
|
|
52
|
+
};
|
|
53
|
+
}, []);
|
|
54
|
+
return actorRef;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function useActor(logic, options = {}) {
|
|
58
|
+
if (!!logic && 'send' in logic && typeof logic.send === 'function') {
|
|
59
|
+
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.`);
|
|
60
|
+
}
|
|
61
|
+
const actorRef = useIdleInterpreter(logic, options);
|
|
62
|
+
const getSnapshot = useCallback(() => {
|
|
63
|
+
return actorRef.getSnapshot();
|
|
64
|
+
}, [actorRef]);
|
|
65
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
66
|
+
const {
|
|
67
|
+
unsubscribe
|
|
68
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
69
|
+
return unsubscribe;
|
|
70
|
+
}, [actorRef]);
|
|
71
|
+
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
actorRef.start();
|
|
74
|
+
return () => {
|
|
75
|
+
actorRef.stop();
|
|
76
|
+
actorRef.status = ActorStatus.NotStarted;
|
|
77
|
+
actorRef._initState();
|
|
78
|
+
};
|
|
79
|
+
}, [actorRef]);
|
|
80
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function defaultCompare(a, b) {
|
|
84
|
+
return a === b;
|
|
85
|
+
}
|
|
86
|
+
function useSelector(actor, selector, compare = defaultCompare) {
|
|
87
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
88
|
+
const {
|
|
89
|
+
unsubscribe
|
|
90
|
+
} = actor.subscribe(handleStoreChange);
|
|
91
|
+
return unsubscribe;
|
|
92
|
+
}, [actor]);
|
|
93
|
+
const boundGetSnapshot = useCallback(() => actor.getSnapshot(), [actor]);
|
|
94
|
+
const selectedSnapshot = useSyncExternalStoreWithSelector(subscribe, boundGetSnapshot, boundGetSnapshot, selector, compare);
|
|
95
|
+
return selectedSnapshot;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
99
|
+
function is(x, y) {
|
|
100
|
+
if (x === y) {
|
|
101
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y;
|
|
102
|
+
} else {
|
|
103
|
+
return x !== x && y !== y;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function shallowEqual(objA, objB) {
|
|
107
|
+
if (is(objA, objB)) return true;
|
|
108
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const keysA = Object.keys(objA);
|
|
112
|
+
const keysB = Object.keys(objB);
|
|
113
|
+
if (keysA.length !== keysB.length) return false;
|
|
114
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
115
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function createActorContext(actorLogic, interpreterOptions) {
|
|
123
|
+
const ReactContext = /*#__PURE__*/React.createContext(null);
|
|
124
|
+
const OriginalProvider = ReactContext.Provider;
|
|
125
|
+
function Provider({
|
|
126
|
+
children,
|
|
127
|
+
logic: providedLogic = actorLogic,
|
|
128
|
+
machine,
|
|
129
|
+
options: providedOptions = interpreterOptions
|
|
130
|
+
}) {
|
|
131
|
+
if (machine) {
|
|
132
|
+
throw new Error(`The "machine" prop has been deprecated. Please use "logic" instead.`);
|
|
133
|
+
}
|
|
134
|
+
const actor = useActorRef(providedLogic, providedOptions);
|
|
135
|
+
return /*#__PURE__*/React.createElement(OriginalProvider, {
|
|
136
|
+
value: actor,
|
|
137
|
+
children
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// TODO: add properties to actor ref to make more descriptive
|
|
142
|
+
Provider.displayName = `ActorProvider`;
|
|
143
|
+
function useContext() {
|
|
144
|
+
const actor = React.useContext(ReactContext);
|
|
145
|
+
if (!actor) {
|
|
146
|
+
throw new Error(`You used a hook from "${Provider.displayName}" but it's not inside a <${Provider.displayName}> component.`);
|
|
147
|
+
}
|
|
148
|
+
return actor;
|
|
149
|
+
}
|
|
150
|
+
function useSelector$1(selector, compare) {
|
|
151
|
+
const actor = useContext();
|
|
152
|
+
return useSelector(actor, selector, compare);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
Provider: Provider,
|
|
156
|
+
useActorRef: useContext,
|
|
157
|
+
useSelector: useSelector$1
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @alias useActor
|
|
163
|
+
*/
|
|
164
|
+
function useMachine(machine, options = {}) {
|
|
165
|
+
return useActor(machine, options);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { createActorContext, shallowEqual, useActor, useActorRef, useMachine, useSelector };
|
package/dist/xstate-react.esm.js
CHANGED
|
@@ -1,251 +1,91 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useEffect,
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useEffect, useCallback } from 'react';
|
|
3
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
4
|
+
import { toObserver, ActorStatus, createActor } from 'xstate';
|
|
3
5
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
4
6
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
5
|
-
import { toObserver, InterpreterStatus, interpret } from 'xstate';
|
|
6
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
|
-
|
|
8
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
9
|
-
if (source == null) return {};
|
|
10
|
-
var target = {};
|
|
11
|
-
var sourceKeys = Object.keys(source);
|
|
12
|
-
var key, i;
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return target;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function _objectWithoutProperties(source, excluded) {
|
|
24
|
-
if (source == null) return {};
|
|
25
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
26
|
-
var key, i;
|
|
27
|
-
|
|
28
|
-
if (Object.getOwnPropertySymbols) {
|
|
29
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
30
|
-
|
|
31
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
32
|
-
key = sourceSymbolKeys[i];
|
|
33
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
34
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
35
|
-
target[key] = source[key];
|
|
36
|
-
}
|
|
8
|
+
function useConstant(fn) {
|
|
9
|
+
const ref = React.useRef();
|
|
10
|
+
if (!ref.current) {
|
|
11
|
+
ref.current = {
|
|
12
|
+
v: fn()
|
|
13
|
+
};
|
|
37
14
|
}
|
|
38
|
-
|
|
39
|
-
return target;
|
|
15
|
+
return ref.current.v;
|
|
40
16
|
}
|
|
41
17
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return typeof getMachine === 'function' ? getMachine() : getMachine;
|
|
18
|
+
function useIdleInterpreter(machine, options) {
|
|
19
|
+
const actorRef = useConstant(() => {
|
|
20
|
+
return createActor(machine, options);
|
|
46
21
|
});
|
|
47
22
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (getMachine !== initialMachine) {
|
|
54
|
-
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' + 'Please make sure that you pass the same Machine as argument each time.');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
var context = options.context,
|
|
59
|
-
actors = options.actors,
|
|
60
|
-
guards = options.guards,
|
|
61
|
-
actions = options.actions,
|
|
62
|
-
delays = options.delays,
|
|
63
|
-
rehydratedState = options.state,
|
|
64
|
-
interpreterOptions = _objectWithoutProperties(options, _excluded);
|
|
65
|
-
|
|
66
|
-
var service = useConstant(function () {
|
|
67
|
-
var machineConfig = {
|
|
68
|
-
context: context,
|
|
69
|
-
guards: guards,
|
|
70
|
-
actions: actions,
|
|
71
|
-
actors: actors,
|
|
72
|
-
delays: delays
|
|
73
|
-
};
|
|
74
|
-
var machineWithConfig = machine.provide(machineConfig);
|
|
75
|
-
return interpret(machineWithConfig, interpreterOptions);
|
|
76
|
-
}); // Make sure options are kept updated when they change.
|
|
77
|
-
// This mutation assignment is safe because the service instance is only used
|
|
78
|
-
// in one place -- this hook's caller.
|
|
79
|
-
|
|
80
|
-
useIsomorphicLayoutEffect(function () {
|
|
81
|
-
Object.assign(service.behavior.options.actions, actions);
|
|
82
|
-
Object.assign(service.behavior.options.guards, guards);
|
|
83
|
-
Object.assign(service.behavior.options.actors, actors);
|
|
84
|
-
Object.assign(service.behavior.options.delays, delays);
|
|
85
|
-
}, [actions, guards, actors, delays]);
|
|
86
|
-
return service;
|
|
23
|
+
// TODO: consider using `useAsapEffect` that would do this in `useInsertionEffect` is that's available
|
|
24
|
+
useIsomorphicLayoutEffect(() => {
|
|
25
|
+
actorRef.logic.implementations = machine.implementations;
|
|
26
|
+
});
|
|
27
|
+
return actorRef;
|
|
87
28
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
var _ref$ = _ref[0],
|
|
94
|
-
options = _ref$ === void 0 ? {} : _ref$,
|
|
95
|
-
observerOrListener = _ref[1];
|
|
96
|
-
var service = useIdleInterpreter(getMachine, options);
|
|
97
|
-
useEffect(function () {
|
|
29
|
+
function useActorRef(machine, ...[options = {}, observerOrListener]) {
|
|
30
|
+
const actorRef = useIdleInterpreter(machine, options);
|
|
31
|
+
useEffect(() => {
|
|
98
32
|
if (!observerOrListener) {
|
|
99
33
|
return;
|
|
100
34
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return function () {
|
|
35
|
+
let sub = actorRef.subscribe(toObserver(observerOrListener));
|
|
36
|
+
return () => {
|
|
104
37
|
sub.unsubscribe();
|
|
105
38
|
};
|
|
106
39
|
}, [observerOrListener]);
|
|
107
|
-
useEffect(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
actorRef.start();
|
|
42
|
+
return () => {
|
|
43
|
+
actorRef.stop();
|
|
44
|
+
actorRef.status = ActorStatus.NotStarted;
|
|
45
|
+
actorRef._initState();
|
|
113
46
|
};
|
|
114
47
|
}, []);
|
|
115
|
-
return
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function identity(a) {
|
|
119
|
-
return a;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
var isEqual = function isEqual(prevState, nextState) {
|
|
123
|
-
return prevState === nextState || nextState.changed === false;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// TODO: rethink how we can do this better
|
|
127
|
-
var cachedRehydratedStates = new WeakMap();
|
|
128
|
-
function useMachine(getMachine) {
|
|
129
|
-
for (var _len = arguments.length, _ref = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
130
|
-
_ref[_key - 1] = arguments[_key];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
var _ref$ = _ref[0],
|
|
134
|
-
options = _ref$ === void 0 ? {} : _ref$;
|
|
135
|
-
// using `useIdleInterpreter` allows us to subscribe to the service *before* we start it
|
|
136
|
-
// so we don't miss any notifications
|
|
137
|
-
var service = useIdleInterpreter(getMachine, options);
|
|
138
|
-
var getSnapshot = useCallback(function () {
|
|
139
|
-
if (service.status === InterpreterStatus.NotStarted && options.state) {
|
|
140
|
-
var cached = cachedRehydratedStates.get(options.state);
|
|
141
|
-
|
|
142
|
-
if (cached) {
|
|
143
|
-
return cached;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
var created = service.behavior.createState(options.state);
|
|
147
|
-
cachedRehydratedStates.set(options.state, created);
|
|
148
|
-
return created;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return service.getSnapshot();
|
|
152
|
-
}, [service]);
|
|
153
|
-
var subscribe = useCallback(function (handleStoreChange) {
|
|
154
|
-
var _service$subscribe = service.subscribe(handleStoreChange),
|
|
155
|
-
unsubscribe = _service$subscribe.unsubscribe;
|
|
156
|
-
|
|
157
|
-
return unsubscribe;
|
|
158
|
-
}, [service]);
|
|
159
|
-
var storeSnapshot = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity, isEqual);
|
|
160
|
-
useEffect(function () {
|
|
161
|
-
var rehydratedState = options.state;
|
|
162
|
-
service.start(rehydratedState ? service.behavior.createState(rehydratedState) : undefined);
|
|
163
|
-
return function () {
|
|
164
|
-
service.stop();
|
|
165
|
-
service.status = InterpreterStatus.NotStarted;
|
|
166
|
-
};
|
|
167
|
-
}, []);
|
|
168
|
-
return [storeSnapshot, service.send, service];
|
|
48
|
+
return actorRef;
|
|
169
49
|
}
|
|
170
50
|
|
|
171
|
-
function useActor(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
unsubscribe = _actorRef$subscribe.unsubscribe;
|
|
175
|
-
|
|
176
|
-
return unsubscribe;
|
|
177
|
-
}, [actorRef]);
|
|
178
|
-
var boundGetSnapshot = useCallback(function () {
|
|
51
|
+
function useActor(logic, options = {}) {
|
|
52
|
+
const actorRef = useIdleInterpreter(logic, options);
|
|
53
|
+
const getSnapshot = useCallback(() => {
|
|
179
54
|
return actorRef.getSnapshot();
|
|
180
55
|
}, [actorRef]);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
56
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
57
|
+
const {
|
|
58
|
+
unsubscribe
|
|
59
|
+
} = actorRef.subscribe(handleStoreChange);
|
|
60
|
+
return unsubscribe;
|
|
61
|
+
}, [actorRef]);
|
|
62
|
+
const actorSnapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
actorRef.start();
|
|
65
|
+
return () => {
|
|
66
|
+
actorRef.stop();
|
|
67
|
+
actorRef.status = ActorStatus.NotStarted;
|
|
68
|
+
actorRef._initState();
|
|
69
|
+
};
|
|
184
70
|
}, [actorRef]);
|
|
185
|
-
return [
|
|
71
|
+
return [actorSnapshot, actorRef.send, actorRef];
|
|
186
72
|
}
|
|
187
73
|
|
|
188
74
|
function defaultCompare(a, b) {
|
|
189
75
|
return a === b;
|
|
190
76
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
unsubscribe = _actor$subscribe.unsubscribe;
|
|
197
|
-
|
|
77
|
+
function useSelector(actor, selector, compare = defaultCompare) {
|
|
78
|
+
const subscribe = useCallback(handleStoreChange => {
|
|
79
|
+
const {
|
|
80
|
+
unsubscribe
|
|
81
|
+
} = actor.subscribe(handleStoreChange);
|
|
198
82
|
return unsubscribe;
|
|
199
83
|
}, [actor]);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}, [actor]);
|
|
203
|
-
var selectedSnapshot = useSyncExternalStoreWithSelector(subscribe, boundGetSnapshot, boundGetSnapshot, selector, compare);
|
|
84
|
+
const boundGetSnapshot = useCallback(() => actor.getSnapshot(), [actor]);
|
|
85
|
+
const selectedSnapshot = useSyncExternalStoreWithSelector(subscribe, boundGetSnapshot, boundGetSnapshot, selector, compare);
|
|
204
86
|
return selectedSnapshot;
|
|
205
87
|
}
|
|
206
88
|
|
|
207
|
-
/**
|
|
208
|
-
* React hook that spawns an `ActorRef` with the specified `behavior`.
|
|
209
|
-
* The returned `ActorRef` can be used with the `useActor(actorRef)` hook.
|
|
210
|
-
*
|
|
211
|
-
* @param behavior The actor behavior to spawn
|
|
212
|
-
* @returns An ActorRef with the specified `behavior`
|
|
213
|
-
*/
|
|
214
|
-
|
|
215
|
-
function useSpawn(behavior) {
|
|
216
|
-
var actorRef = useConstant(function () {
|
|
217
|
-
// TODO: figure out what to do about the name argument
|
|
218
|
-
return interpret(behavior);
|
|
219
|
-
});
|
|
220
|
-
useEffect(function () {
|
|
221
|
-
var _actorRef$start;
|
|
222
|
-
|
|
223
|
-
(_actorRef$start = actorRef.start) === null || _actorRef$start === void 0 ? void 0 : _actorRef$start.call(actorRef);
|
|
224
|
-
return function () {
|
|
225
|
-
var _stop, _ref;
|
|
226
|
-
|
|
227
|
-
(_stop = (_ref = actorRef).stop) === null || _stop === void 0 ? void 0 : _stop.call(_ref);
|
|
228
|
-
};
|
|
229
|
-
}, []);
|
|
230
|
-
return actorRef;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function _typeof(obj) {
|
|
234
|
-
"@babel/helpers - typeof";
|
|
235
|
-
|
|
236
|
-
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
237
|
-
_typeof = function (obj) {
|
|
238
|
-
return typeof obj;
|
|
239
|
-
};
|
|
240
|
-
} else {
|
|
241
|
-
_typeof = function (obj) {
|
|
242
|
-
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return _typeof(obj);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
89
|
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts
|
|
250
90
|
function is(x, y) {
|
|
251
91
|
if (x === y) {
|
|
@@ -254,25 +94,66 @@ function is(x, y) {
|
|
|
254
94
|
return x !== x && y !== y;
|
|
255
95
|
}
|
|
256
96
|
}
|
|
257
|
-
|
|
258
97
|
function shallowEqual(objA, objB) {
|
|
259
98
|
if (is(objA, objB)) return true;
|
|
260
|
-
|
|
261
|
-
if (_typeof(objA) !== 'object' || objA === null || _typeof(objB) !== 'object' || objB === null) {
|
|
99
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
262
100
|
return false;
|
|
263
101
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
var keysB = Object.keys(objB);
|
|
102
|
+
const keysA = Object.keys(objA);
|
|
103
|
+
const keysB = Object.keys(objB);
|
|
267
104
|
if (keysA.length !== keysB.length) return false;
|
|
268
|
-
|
|
269
|
-
for (var i = 0; i < keysA.length; i++) {
|
|
105
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
270
106
|
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
|
|
271
107
|
return false;
|
|
272
108
|
}
|
|
273
109
|
}
|
|
274
|
-
|
|
275
110
|
return true;
|
|
276
111
|
}
|
|
277
112
|
|
|
278
|
-
|
|
113
|
+
function createActorContext(actorLogic, interpreterOptions) {
|
|
114
|
+
const ReactContext = /*#__PURE__*/React.createContext(null);
|
|
115
|
+
const OriginalProvider = ReactContext.Provider;
|
|
116
|
+
function Provider({
|
|
117
|
+
children,
|
|
118
|
+
logic: providedLogic = actorLogic,
|
|
119
|
+
machine,
|
|
120
|
+
options: providedOptions = interpreterOptions
|
|
121
|
+
}) {
|
|
122
|
+
if (machine) {
|
|
123
|
+
throw new Error(`The "machine" prop has been deprecated. Please use "logic" instead.`);
|
|
124
|
+
}
|
|
125
|
+
const actor = useActorRef(providedLogic, providedOptions);
|
|
126
|
+
return /*#__PURE__*/React.createElement(OriginalProvider, {
|
|
127
|
+
value: actor,
|
|
128
|
+
children
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// TODO: add properties to actor ref to make more descriptive
|
|
133
|
+
Provider.displayName = `ActorProvider`;
|
|
134
|
+
function useContext() {
|
|
135
|
+
const actor = React.useContext(ReactContext);
|
|
136
|
+
if (!actor) {
|
|
137
|
+
throw new Error(`You used a hook from "${Provider.displayName}" but it's not inside a <${Provider.displayName}> component.`);
|
|
138
|
+
}
|
|
139
|
+
return actor;
|
|
140
|
+
}
|
|
141
|
+
function useSelector$1(selector, compare) {
|
|
142
|
+
const actor = useContext();
|
|
143
|
+
return useSelector(actor, selector, compare);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
Provider: Provider,
|
|
147
|
+
useActorRef: useContext,
|
|
148
|
+
useSelector: useSelector$1
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @alias useActor
|
|
154
|
+
*/
|
|
155
|
+
function useMachine(machine, options = {}) {
|
|
156
|
+
return useActor(machine, options);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { createActorContext, shallowEqual, useActor, useActorRef, useMachine, useSelector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xstate/react",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-beta.10",
|
|
4
4
|
"description": "XState tools for React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -18,21 +18,32 @@
|
|
|
18
18
|
"main": "dist/xstate-react.cjs.js",
|
|
19
19
|
"module": "dist/xstate-react.esm.js",
|
|
20
20
|
"exports": {
|
|
21
|
-
"./fsm": {
|
|
22
|
-
"module": "./fsm/dist/xstate-react-fsm.esm.js",
|
|
23
|
-
"default": "./fsm/dist/xstate-react-fsm.cjs.js"
|
|
24
|
-
},
|
|
25
21
|
".": {
|
|
22
|
+
"types": {
|
|
23
|
+
"import": "./dist/xstate-react.cjs.mjs",
|
|
24
|
+
"default": "./dist/xstate-react.cjs.js"
|
|
25
|
+
},
|
|
26
|
+
"development": {
|
|
27
|
+
"module": "./dist/xstate-react.development.esm.js",
|
|
28
|
+
"import": "./dist/xstate-react.development.cjs.mjs",
|
|
29
|
+
"default": "./dist/xstate-react.development.cjs.js"
|
|
30
|
+
},
|
|
26
31
|
"module": "./dist/xstate-react.esm.js",
|
|
32
|
+
"import": "./dist/xstate-react.cjs.mjs",
|
|
27
33
|
"default": "./dist/xstate-react.cjs.js"
|
|
28
34
|
},
|
|
29
35
|
"./package.json": "./package.json"
|
|
30
36
|
},
|
|
37
|
+
"imports": {
|
|
38
|
+
"#is-development": {
|
|
39
|
+
"development": "./src/true.ts",
|
|
40
|
+
"default": "./src/false.ts"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
31
43
|
"types": "dist/xstate-react.cjs.d.ts",
|
|
32
44
|
"sideEffects": false,
|
|
33
45
|
"files": [
|
|
34
|
-
"dist"
|
|
35
|
-
"fsm"
|
|
46
|
+
"dist"
|
|
36
47
|
],
|
|
37
48
|
"repository": {
|
|
38
49
|
"type": "git",
|
|
@@ -43,39 +54,28 @@
|
|
|
43
54
|
"url": "https://github.com/statelyai/xstate/issues"
|
|
44
55
|
},
|
|
45
56
|
"peerDependencies": {
|
|
46
|
-
"@xstate/fsm": "^3.0.0-alpha.0",
|
|
47
57
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
48
|
-
"xstate": "^5.0.0-
|
|
58
|
+
"xstate": "^5.0.0-beta.29"
|
|
49
59
|
},
|
|
50
60
|
"peerDependenciesMeta": {
|
|
51
|
-
"@xstate/fsm": {
|
|
52
|
-
"optional": true
|
|
53
|
-
},
|
|
54
61
|
"xstate": {
|
|
55
62
|
"optional": true
|
|
56
63
|
}
|
|
57
64
|
},
|
|
58
65
|
"dependencies": {
|
|
59
|
-
"use-isomorphic-layout-effect": "^1.
|
|
66
|
+
"use-isomorphic-layout-effect": "^1.1.2",
|
|
60
67
|
"use-sync-external-store": "^1.0.0"
|
|
61
68
|
},
|
|
62
69
|
"devDependencies": {
|
|
63
|
-
"@testing-library/react": "^13.
|
|
70
|
+
"@testing-library/react": "^13.4.0",
|
|
64
71
|
"@types/jsdom": "^12.2.3",
|
|
65
72
|
"@types/react": "^17.0.43",
|
|
66
73
|
"@types/react-dom": "^17.0.14",
|
|
67
74
|
"@types/use-sync-external-store": "^0.0.3",
|
|
68
|
-
"@xstate/fsm": "3.0.0-alpha.0",
|
|
69
75
|
"jsdom": "^14.0.0",
|
|
70
76
|
"jsdom-global": "^3.0.2",
|
|
71
77
|
"react": "^18.0.0",
|
|
72
78
|
"react-dom": "^18.0.0",
|
|
73
|
-
"xstate": "5.0.0-
|
|
74
|
-
},
|
|
75
|
-
"preconstruct": {
|
|
76
|
-
"entrypoints": [
|
|
77
|
-
"./index.ts",
|
|
78
|
-
"./fsm.ts"
|
|
79
|
-
]
|
|
79
|
+
"xstate": "5.0.0-beta.29"
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { MachineImplementationsFrom, ServiceFrom, StateFrom, StateMachine } from '@xstate/fsm';
|
|
2
|
-
export declare function useMachine<TMachine extends StateMachine.AnyMachine>(stateMachine: TMachine, options?: MachineImplementationsFrom<TMachine>): [StateFrom<TMachine>, ServiceFrom<TMachine>['send'], ServiceFrom<TMachine>];
|
|
3
|
-
export declare function useService<TService extends StateMachine.AnyService>(service: TService): [StateFrom<TService>, TService['send'], TService];
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { EventObject, MachineContext, StateConfig } from 'xstate';
|
|
2
|
-
export declare type MaybeLazy<T> = T | (() => T);
|
|
3
|
-
export declare type NoInfer<T> = [T][T extends any ? 0 : any];
|
|
4
|
-
export declare type Prop<T, K> = K extends keyof T ? T[K] : never;
|
|
5
|
-
export interface UseMachineOptions<TContext extends MachineContext, TEvent extends EventObject> {
|
|
6
|
-
/**
|
|
7
|
-
* If provided, will be merged with machine's `context`.
|
|
8
|
-
*/
|
|
9
|
-
context?: Partial<TContext>;
|
|
10
|
-
/**
|
|
11
|
-
* The state to rehydrate the machine to. The machine will
|
|
12
|
-
* start at this state instead of its `initialState`.
|
|
13
|
-
*/
|
|
14
|
-
state?: StateConfig<TContext, TEvent>;
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function useConstant<T>(fn: () => T): T;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { AnyInterpreter, AnyStateMachine, AreAllImplementationsAssumedToBeProvided, InternalMachineImplementations, InterpreterFrom, InterpreterOptions, MachineImplementations, Observer, StateFrom } from 'xstate';
|
|
2
|
-
import { MaybeLazy } from './types';
|
|
3
|
-
import { UseMachineOptions } from './useMachine';
|
|
4
|
-
export declare function useIdleInterpreter(getMachine: MaybeLazy<AnyStateMachine>, options: Partial<InterpreterOptions> & Partial<UseMachineOptions<any, never>> & Partial<MachineImplementations<any, never>>): AnyInterpreter;
|
|
5
|
-
declare type RestParams<TMachine extends AnyStateMachine> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [
|
|
6
|
-
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineImplementations<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true>,
|
|
7
|
-
observerOrListener?: Observer<StateFrom<TMachine>> | ((value: StateFrom<TMachine>) => void)
|
|
8
|
-
] : [
|
|
9
|
-
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineImplementations<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']>,
|
|
10
|
-
observerOrListener?: Observer<StateFrom<TMachine>> | ((value: StateFrom<TMachine>) => void)
|
|
11
|
-
];
|
|
12
|
-
export declare function useInterpret<TMachine extends AnyStateMachine>(getMachine: MaybeLazy<TMachine>, ...[options, observerOrListener]: RestParams<TMachine>): InterpreterFrom<TMachine>;
|
|
13
|
-
export {};
|