@xstate/react 2.0.0-pr2674-2021926101023 → 3.0.0
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/CHANGELOG.md +65 -28
- package/dist/xstate-react-fsm.umd.min.js +41 -15
- package/dist/xstate-react.umd.min.js +34 -23
- package/es/fsm.d.ts +3 -19
- package/es/fsm.js +35 -26
- package/es/index.d.ts +1 -2
- package/es/index.js +1 -2
- package/es/types.d.ts +1 -16
- package/es/types.js +1 -5
- package/es/useActor.js +13 -32
- package/es/useInterpret.d.ts +6 -5
- package/es/useInterpret.js +32 -43
- package/es/useMachine.d.ts +5 -7
- package/es/useMachine.js +39 -44
- package/es/useSelector.js +12 -48
- package/es/useSpawn.js +1 -1
- package/es/utils.d.ts +2 -0
- package/es/utils.js +3 -0
- package/lib/fsm.d.ts +3 -19
- package/lib/fsm.js +36 -27
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -5
- package/lib/types.d.ts +1 -16
- package/lib/types.js +0 -6
- package/lib/useActor.js +16 -35
- package/lib/useInterpret.d.ts +6 -5
- package/lib/useInterpret.js +35 -45
- package/lib/useMachine.d.ts +5 -7
- package/lib/useMachine.js +37 -44
- package/lib/useSelector.js +13 -49
- package/lib/useSpawn.js +3 -3
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +5 -1
- package/package.json +17 -16
- package/dist/xstate-react.cjs.js +0 -16
- package/es/useReactEffectActions.d.ts +0 -3
- package/es/useReactEffectActions.js +0 -72
- package/es/useService.d.ts +0 -16
- package/es/useService.js +0 -36
- package/lib/useReactEffectActions.d.ts +0 -3
- package/lib/useReactEffectActions.js +0 -76
- package/lib/useService.d.ts +0 -16
- package/lib/useService.js +0 -41
package/es/useActor.js
CHANGED
|
@@ -1,31 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
3
|
-
if (!m) return o;
|
|
4
|
-
var i = m.call(o), r, ar = [], e;
|
|
5
|
-
try {
|
|
6
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
7
|
-
}
|
|
8
|
-
catch (error) { e = { error: error }; }
|
|
9
|
-
finally {
|
|
10
|
-
try {
|
|
11
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
12
|
-
}
|
|
13
|
-
finally { if (e) throw e.error; }
|
|
14
|
-
}
|
|
15
|
-
return ar;
|
|
16
|
-
};
|
|
17
|
-
import { useState, useRef } from 'react';
|
|
1
|
+
import { useRef, useCallback } from 'react';
|
|
18
2
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
19
3
|
import useConstant from './useConstant';
|
|
4
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
20
5
|
export function isActorWithState(actorRef) {
|
|
21
6
|
return 'state' in actorRef;
|
|
22
7
|
}
|
|
23
8
|
function isDeferredActor(actorRef) {
|
|
24
9
|
return 'deferred' in actorRef;
|
|
25
10
|
}
|
|
26
|
-
var noop = function () {
|
|
27
|
-
/* ... */
|
|
28
|
-
};
|
|
29
11
|
function defaultGetSnapshot(actorRef) {
|
|
30
12
|
return 'getSnapshot' in actorRef
|
|
31
13
|
? actorRef.getSnapshot()
|
|
@@ -37,7 +19,15 @@ export function useActor(actorRef, getSnapshot) {
|
|
|
37
19
|
if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; }
|
|
38
20
|
var actorRefRef = useRef(actorRef);
|
|
39
21
|
var deferredEventsRef = useRef([]);
|
|
40
|
-
var
|
|
22
|
+
var subscribe = useCallback(function (handleStoreChange) {
|
|
23
|
+
var unsubscribe = actorRef.subscribe(handleStoreChange).unsubscribe;
|
|
24
|
+
return unsubscribe;
|
|
25
|
+
}, [actorRef]);
|
|
26
|
+
var boundGetSnapshot = useCallback(function () { return getSnapshot(actorRef); }, [
|
|
27
|
+
actorRef,
|
|
28
|
+
getSnapshot
|
|
29
|
+
]);
|
|
30
|
+
var storeSnapshot = useSyncExternalStore(subscribe, boundGetSnapshot, boundGetSnapshot);
|
|
41
31
|
var send = useConstant(function () { return function () {
|
|
42
32
|
var args = [];
|
|
43
33
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
@@ -45,7 +35,7 @@ export function useActor(actorRef, getSnapshot) {
|
|
|
45
35
|
}
|
|
46
36
|
var event = args[0];
|
|
47
37
|
if (process.env.NODE_ENV !== 'production' && args.length > 1) {
|
|
48
|
-
console.warn("Unexpected payload: "
|
|
38
|
+
console.warn("Unexpected payload: ".concat(JSON.stringify(args[1]), ". Only a single event object can be sent to actor send() functions."));
|
|
49
39
|
}
|
|
50
40
|
var currentActorRef = actorRefRef.current;
|
|
51
41
|
// If the previous actor is a deferred actor,
|
|
@@ -60,20 +50,11 @@ export function useActor(actorRef, getSnapshot) {
|
|
|
60
50
|
}; });
|
|
61
51
|
useIsomorphicLayoutEffect(function () {
|
|
62
52
|
actorRefRef.current = actorRef;
|
|
63
|
-
setCurrent(getSnapshot(actorRef));
|
|
64
|
-
var subscription = actorRef.subscribe({
|
|
65
|
-
next: function (emitted) { return setCurrent(emitted); },
|
|
66
|
-
error: noop,
|
|
67
|
-
complete: noop
|
|
68
|
-
});
|
|
69
53
|
// Dequeue deferred events from the previous deferred actorRef
|
|
70
54
|
while (deferredEventsRef.current.length > 0) {
|
|
71
55
|
var deferredEvent = deferredEventsRef.current.shift();
|
|
72
56
|
actorRef.send(deferredEvent);
|
|
73
57
|
}
|
|
74
|
-
return function () {
|
|
75
|
-
subscription.unsubscribe();
|
|
76
|
-
};
|
|
77
58
|
}, [actorRef]);
|
|
78
|
-
return [
|
|
59
|
+
return [storeSnapshot, send];
|
|
79
60
|
}
|
package/es/useInterpret.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { AreAllImplementationsAssumedToBeProvided, InternalMachineOptions, InterpreterFrom, InterpreterOptions,
|
|
1
|
+
import { AnyInterpreter, AnyStateMachine, AreAllImplementationsAssumedToBeProvided, InternalMachineOptions, InterpreterFrom, InterpreterOptions, MachineOptions, Observer, StateFrom } from 'xstate';
|
|
2
2
|
import { MaybeLazy } from './types';
|
|
3
3
|
import { UseMachineOptions } from './useMachine';
|
|
4
|
-
declare
|
|
4
|
+
export declare function useIdleInterpreter(getMachine: MaybeLazy<AnyStateMachine>, options: Partial<InterpreterOptions> & Partial<UseMachineOptions<unknown, never>> & Partial<MachineOptions<unknown, never>>): AnyInterpreter;
|
|
5
|
+
declare type RestParams<TMachine extends AnyStateMachine> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [
|
|
5
6
|
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true>,
|
|
6
|
-
observerOrListener?: Observer<
|
|
7
|
+
observerOrListener?: Observer<StateFrom<TMachine>> | ((value: StateFrom<TMachine>) => void)
|
|
7
8
|
] : [
|
|
8
9
|
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']>,
|
|
9
|
-
observerOrListener?: Observer<
|
|
10
|
+
observerOrListener?: Observer<StateFrom<TMachine>> | ((value: StateFrom<TMachine>) => void)
|
|
10
11
|
];
|
|
11
|
-
export declare function useInterpret<TMachine extends
|
|
12
|
+
export declare function useInterpret<TMachine extends AnyStateMachine>(getMachine: MaybeLazy<TMachine>, ...[options, observerOrListener]: RestParams<TMachine>): InterpreterFrom<TMachine>;
|
|
12
13
|
export {};
|
|
13
14
|
//# sourceMappingURL=useInterpret.d.ts.map
|
package/es/useInterpret.js
CHANGED
|
@@ -36,44 +36,23 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
36
36
|
}
|
|
37
37
|
return ar;
|
|
38
38
|
};
|
|
39
|
-
import { useState } from 'react';
|
|
39
|
+
import { useEffect, useState } from 'react';
|
|
40
40
|
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
41
|
-
import { interpret, State } from 'xstate';
|
|
41
|
+
import { interpret, InterpreterStatus, State, toObserver } from 'xstate';
|
|
42
42
|
import useConstant from './useConstant';
|
|
43
|
-
|
|
44
|
-
// copied from core/src/utils.ts
|
|
45
|
-
// it avoids a breaking change between this package and XState which is its peer dep
|
|
46
|
-
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
47
|
-
if (typeof nextHandler === 'object') {
|
|
48
|
-
return nextHandler;
|
|
49
|
-
}
|
|
50
|
-
var noop = function () { return void 0; };
|
|
51
|
-
return {
|
|
52
|
-
next: nextHandler,
|
|
53
|
-
error: errorHandler || noop,
|
|
54
|
-
complete: completionHandler || noop
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
export function useInterpret(getMachine) {
|
|
58
|
-
var _a = [];
|
|
59
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
60
|
-
_a[_i - 1] = arguments[_i];
|
|
61
|
-
}
|
|
62
|
-
var _b = __read(_a, 2), _c = _b[0], options = _c === void 0 ? {} : _c, observerOrListener = _b[1];
|
|
43
|
+
export function useIdleInterpreter(getMachine, options) {
|
|
63
44
|
var machine = useConstant(function () {
|
|
64
45
|
return typeof getMachine === 'function' ? getMachine() : getMachine;
|
|
65
46
|
});
|
|
66
47
|
if (process.env.NODE_ENV !== 'production' &&
|
|
67
48
|
typeof getMachine !== 'function') {
|
|
68
|
-
var
|
|
49
|
+
var _a = __read(useState(machine), 1), initialMachine = _a[0];
|
|
69
50
|
if (getMachine !== initialMachine) {
|
|
70
51
|
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' +
|
|
71
52
|
'Please make sure that you pass the same Machine as argument each time.');
|
|
72
53
|
}
|
|
73
54
|
}
|
|
74
|
-
var context = options.context, guards = options.guards, actions = options.actions, services = options.services, delays = options.delays, rehydratedState = options.state, interpreterOptions = __rest(options, ["context", "guards", "actions", "services", "delays", "state"]);
|
|
75
|
-
// it's not defined in `TypegenMachineOptions` so we can't just unpack this property here freely
|
|
76
|
-
var activities = options.activities;
|
|
55
|
+
var context = options.context, guards = options.guards, actions = options.actions, activities = options.activities, services = options.services, delays = options.delays, rehydratedState = options.state, interpreterOptions = __rest(options, ["context", "guards", "actions", "activities", "services", "delays", "state"]);
|
|
77
56
|
var service = useConstant(function () {
|
|
78
57
|
var machineConfig = {
|
|
79
58
|
context: context,
|
|
@@ -84,23 +63,8 @@ export function useInterpret(getMachine) {
|
|
|
84
63
|
delays: delays
|
|
85
64
|
};
|
|
86
65
|
var machineWithConfig = machine.withConfig(machineConfig, function () { return (__assign(__assign({}, machine.context), context)); });
|
|
87
|
-
return interpret(machineWithConfig,
|
|
66
|
+
return interpret(machineWithConfig, interpreterOptions);
|
|
88
67
|
});
|
|
89
|
-
useIsomorphicLayoutEffect(function () {
|
|
90
|
-
var sub;
|
|
91
|
-
if (observerOrListener) {
|
|
92
|
-
sub = service.subscribe(toObserver(observerOrListener));
|
|
93
|
-
}
|
|
94
|
-
return function () {
|
|
95
|
-
sub === null || sub === void 0 ? void 0 : sub.unsubscribe();
|
|
96
|
-
};
|
|
97
|
-
}, [observerOrListener]);
|
|
98
|
-
useIsomorphicLayoutEffect(function () {
|
|
99
|
-
service.start(rehydratedState ? State.create(rehydratedState) : undefined);
|
|
100
|
-
return function () {
|
|
101
|
-
service.stop();
|
|
102
|
-
};
|
|
103
|
-
}, []);
|
|
104
68
|
// Make sure options are kept updated when they change.
|
|
105
69
|
// This mutation assignment is safe because the service instance is only used
|
|
106
70
|
// in one place -- this hook's caller.
|
|
@@ -111,6 +75,31 @@ export function useInterpret(getMachine) {
|
|
|
111
75
|
Object.assign(service.machine.options.services, services);
|
|
112
76
|
Object.assign(service.machine.options.delays, delays);
|
|
113
77
|
}, [actions, guards, activities, services, delays]);
|
|
114
|
-
|
|
78
|
+
return service;
|
|
79
|
+
}
|
|
80
|
+
export function useInterpret(getMachine) {
|
|
81
|
+
var _a = [];
|
|
82
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
83
|
+
_a[_i - 1] = arguments[_i];
|
|
84
|
+
}
|
|
85
|
+
var _b = __read(_a, 2), _c = _b[0], options = _c === void 0 ? {} : _c, observerOrListener = _b[1];
|
|
86
|
+
var service = useIdleInterpreter(getMachine, options);
|
|
87
|
+
useEffect(function () {
|
|
88
|
+
if (!observerOrListener) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
var sub = service.subscribe(toObserver(observerOrListener));
|
|
92
|
+
return function () {
|
|
93
|
+
sub.unsubscribe();
|
|
94
|
+
};
|
|
95
|
+
}, [observerOrListener]);
|
|
96
|
+
useEffect(function () {
|
|
97
|
+
var rehydratedState = options.state;
|
|
98
|
+
service.start(rehydratedState ? State.create(rehydratedState) : undefined);
|
|
99
|
+
return function () {
|
|
100
|
+
service.stop();
|
|
101
|
+
service.status = InterpreterStatus.NotStarted;
|
|
102
|
+
};
|
|
103
|
+
}, []);
|
|
115
104
|
return service;
|
|
116
105
|
}
|
package/es/useMachine.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MaybeLazy, Prop
|
|
3
|
-
export declare function asEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>;
|
|
4
|
-
export declare function asLayoutEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>;
|
|
1
|
+
import { AnyStateMachine, AreAllImplementationsAssumedToBeProvided, EventObject, InternalMachineOptions, InterpreterFrom, InterpreterOptions, StateConfig, StateFrom } from 'xstate';
|
|
2
|
+
import { MaybeLazy, Prop } from './types';
|
|
5
3
|
export interface UseMachineOptions<TContext, TEvent extends EventObject> {
|
|
6
4
|
/**
|
|
7
5
|
* If provided, will be merged with machine's `context`.
|
|
@@ -13,12 +11,12 @@ export interface UseMachineOptions<TContext, TEvent extends EventObject> {
|
|
|
13
11
|
*/
|
|
14
12
|
state?: StateConfig<TContext, TEvent>;
|
|
15
13
|
}
|
|
16
|
-
declare type RestParams<TMachine extends
|
|
14
|
+
declare type RestParams<TMachine extends AnyStateMachine> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [
|
|
17
15
|
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true>
|
|
18
16
|
] : [
|
|
19
17
|
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']>
|
|
20
18
|
];
|
|
21
|
-
declare type UseMachineReturn<TMachine extends
|
|
22
|
-
export declare function useMachine<TMachine extends
|
|
19
|
+
declare type UseMachineReturn<TMachine extends AnyStateMachine, TInterpreter = InterpreterFrom<TMachine>> = [StateFrom<TMachine>, Prop<TInterpreter, 'send'>, TInterpreter];
|
|
20
|
+
export declare function useMachine<TMachine extends AnyStateMachine>(getMachine: MaybeLazy<TMachine>, ...[options]: RestParams<TMachine>): UseMachineReturn<TMachine>;
|
|
23
21
|
export {};
|
|
24
22
|
//# sourceMappingURL=useMachine.d.ts.map
|
package/es/useMachine.js
CHANGED
|
@@ -14,37 +14,12 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
14
14
|
}
|
|
15
15
|
return ar;
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import { State } from 'xstate';
|
|
24
|
-
import { ReactEffectType } from './types';
|
|
25
|
-
import { useInterpret } from './useInterpret';
|
|
26
|
-
function createReactActionFunction(exec, tag) {
|
|
27
|
-
var effectExec = function () {
|
|
28
|
-
var args = [];
|
|
29
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
30
|
-
args[_i] = arguments[_i];
|
|
31
|
-
}
|
|
32
|
-
// don't execute; just return
|
|
33
|
-
return function () {
|
|
34
|
-
return exec.apply(void 0, __spreadArray([], __read(args)));
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
Object.defineProperties(effectExec, {
|
|
38
|
-
name: { value: "effect:" + exec.name },
|
|
39
|
-
__effect: { value: tag }
|
|
40
|
-
});
|
|
41
|
-
return effectExec;
|
|
42
|
-
}
|
|
43
|
-
export function asEffect(exec) {
|
|
44
|
-
return createReactActionFunction(exec, ReactEffectType.Effect);
|
|
45
|
-
}
|
|
46
|
-
export function asLayoutEffect(exec) {
|
|
47
|
-
return createReactActionFunction(exec, ReactEffectType.LayoutEffect);
|
|
17
|
+
import { useCallback, useEffect } from 'react';
|
|
18
|
+
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
19
|
+
import { InterpreterStatus, State } from 'xstate';
|
|
20
|
+
import { useIdleInterpreter } from './useInterpret';
|
|
21
|
+
function identity(a) {
|
|
22
|
+
return a;
|
|
48
23
|
}
|
|
49
24
|
export function useMachine(getMachine) {
|
|
50
25
|
var _a = [];
|
|
@@ -52,23 +27,43 @@ export function useMachine(getMachine) {
|
|
|
52
27
|
_a[_i - 1] = arguments[_i];
|
|
53
28
|
}
|
|
54
29
|
var _b = __read(_a, 1), _c = _b[0], options = _c === void 0 ? {} : _c;
|
|
55
|
-
|
|
30
|
+
// using `useIdleInterpreter` allows us to subscribe to the service *before* we start it
|
|
31
|
+
// so we don't miss any notifications
|
|
32
|
+
var service = useIdleInterpreter(getMachine, options);
|
|
33
|
+
var getSnapshot = useCallback(function () {
|
|
34
|
+
if (service.status === InterpreterStatus.NotStarted) {
|
|
35
|
+
return (options.state
|
|
36
|
+
? State.create(options.state)
|
|
37
|
+
: service.machine.initialState);
|
|
38
|
+
}
|
|
39
|
+
return service.state;
|
|
40
|
+
}, [service]);
|
|
41
|
+
var isEqual = useCallback(function (prevState, nextState) {
|
|
42
|
+
if (service.status === InterpreterStatus.NotStarted) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
56
45
|
// Only change the current state if:
|
|
57
46
|
// - the incoming state is the "live" initial state (since it might have new actors)
|
|
58
47
|
// - OR the incoming state actually changed.
|
|
59
48
|
//
|
|
60
49
|
// The "live" initial state will have .changed === undefined.
|
|
61
|
-
var initialStateChanged = nextState.changed === undefined &&
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
var initialStateChanged = nextState.changed === undefined &&
|
|
51
|
+
(Object.keys(nextState.children).length > 0 ||
|
|
52
|
+
typeof prevState.changed === 'boolean');
|
|
53
|
+
return !(nextState.changed || initialStateChanged);
|
|
54
|
+
}, [service]);
|
|
55
|
+
var subscribe = useCallback(function (handleStoreChange) {
|
|
56
|
+
var unsubscribe = service.subscribe(handleStoreChange).unsubscribe;
|
|
57
|
+
return unsubscribe;
|
|
58
|
+
}, [service]);
|
|
59
|
+
var storeSnapshot = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity, isEqual);
|
|
60
|
+
useEffect(function () {
|
|
61
|
+
var rehydratedState = options.state;
|
|
62
|
+
service.start(rehydratedState ? State.create(rehydratedState) : undefined);
|
|
63
|
+
return function () {
|
|
64
|
+
service.stop();
|
|
65
|
+
service.status = InterpreterStatus.NotStarted;
|
|
66
|
+
};
|
|
65
67
|
}, []);
|
|
66
|
-
|
|
67
|
-
var _d = __read(useState(function () {
|
|
68
|
-
var initialState = service.machine.initialState;
|
|
69
|
-
return (options.state
|
|
70
|
-
? State.create(options.state)
|
|
71
|
-
: initialState);
|
|
72
|
-
}), 2), state = _d[0], setState = _d[1];
|
|
73
|
-
return [state, service.send, service];
|
|
68
|
+
return [storeSnapshot, service.send, service];
|
|
74
69
|
}
|
package/es/useSelector.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';
|
|
4
3
|
import { isActorWithState } from './useActor';
|
|
5
|
-
import { getServiceSnapshot } from './
|
|
4
|
+
import { getServiceSnapshot } from './utils';
|
|
6
5
|
function isService(actor) {
|
|
7
6
|
return 'state' in actor && 'machine' in actor;
|
|
8
7
|
}
|
|
@@ -17,49 +16,14 @@ var defaultGetSnapshot = function (a) {
|
|
|
17
16
|
export function useSelector(actor, selector, compare, getSnapshot) {
|
|
18
17
|
if (compare === void 0) { compare = defaultCompare; }
|
|
19
18
|
if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; }
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var current = selector(snapshot);
|
|
24
|
-
var notifySubscriber;
|
|
25
|
-
return {
|
|
26
|
-
getSnapshot: function () { return snapshot; },
|
|
27
|
-
getCurrentValue: function () { return current; },
|
|
28
|
-
setCurrentValue: function (newCurrent) {
|
|
29
|
-
current = newCurrent;
|
|
30
|
-
notifySubscriber === null || notifySubscriber === void 0 ? void 0 : notifySubscriber();
|
|
31
|
-
},
|
|
32
|
-
subscribe: function (callback) {
|
|
33
|
-
notifySubscriber = callback;
|
|
34
|
-
var sub = actor.subscribe(function (emitted) {
|
|
35
|
-
snapshot = emitted;
|
|
36
|
-
var next = latestSelectorRef.current(emitted);
|
|
37
|
-
if (!compare(current, next)) {
|
|
38
|
-
current = next;
|
|
39
|
-
callback();
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return function () {
|
|
43
|
-
sub.unsubscribe();
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
// intentionally omit `getSnapshot` and `compare`
|
|
48
|
-
// - `getSnapshot`: it is only supposed to read the "initial" snapshot of an actor
|
|
49
|
-
// - `compare`: is really supposed to be idempotent and the same throughout the lifetime of this hook (the same assumption is made in React Redux v7)
|
|
19
|
+
var subscribe = useCallback(function (handleStoreChange) {
|
|
20
|
+
var unsubscribe = actor.subscribe(handleStoreChange).unsubscribe;
|
|
21
|
+
return unsubscribe;
|
|
50
22
|
}, [actor]);
|
|
51
|
-
var
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
useIsomorphicLayoutEffect(function () {
|
|
59
|
-
latestSelectorRef.current = selector;
|
|
60
|
-
// required so we don't cause a rerender by setting state (this could create infinite rerendering loop with inline selectors)
|
|
61
|
-
// at the same time we need to update the value within the subscription so new emits can compare against what has been returned to the user as current value
|
|
62
|
-
subscription.setCurrentValue(currentSelected);
|
|
63
|
-
});
|
|
64
|
-
return currentSelected;
|
|
23
|
+
var boundGetSnapshot = useCallback(function () { return getSnapshot(actor); }, [
|
|
24
|
+
actor,
|
|
25
|
+
getSnapshot
|
|
26
|
+
]);
|
|
27
|
+
var selectedSnapshot = useSyncExternalStoreWithSelector(subscribe, boundGetSnapshot, boundGetSnapshot, selector, compare);
|
|
28
|
+
return selectedSnapshot;
|
|
65
29
|
}
|
package/es/useSpawn.js
CHANGED
package/es/utils.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
import { Interpreter } from 'xstate';
|
|
1
2
|
export declare function partition<T, A extends T, B extends T>(items: T[], predicate: (item: T) => item is A): [A[], B[]];
|
|
3
|
+
export declare function getServiceSnapshot<TService extends Interpreter<any, any, any, any>>(service: TService): TService['state'];
|
|
2
4
|
//# sourceMappingURL=utils.d.ts.map
|
package/es/utils.js
CHANGED
package/lib/fsm.d.ts
CHANGED
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function useMachine<
|
|
3
|
-
|
|
4
|
-
context: TContext;
|
|
5
|
-
}>(stateMachine: StateMachine.Machine<TContext, TEvent, TState>, options?: {
|
|
6
|
-
actions?: StateMachine.ActionMap<TContext, TEvent>;
|
|
7
|
-
}): [
|
|
8
|
-
StateMachine.State<TContext, TEvent, TState>,
|
|
9
|
-
StateMachine.Service<TContext, TEvent, TState>['send'],
|
|
10
|
-
StateMachine.Service<TContext, TEvent, TState>
|
|
11
|
-
];
|
|
12
|
-
export declare function useService<TContext extends object, TEvent extends EventObject = EventObject, TState extends Typestate<TContext> = {
|
|
13
|
-
value: any;
|
|
14
|
-
context: TContext;
|
|
15
|
-
}>(service: StateMachine.Service<TContext, TEvent, TState>): [
|
|
16
|
-
StateMachine.State<TContext, TEvent, TState>,
|
|
17
|
-
StateMachine.Service<TContext, TEvent, TState>['send'],
|
|
18
|
-
StateMachine.Service<TContext, TEvent, TState>
|
|
19
|
-
];
|
|
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];
|
|
20
4
|
//# sourceMappingURL=fsm.d.ts.map
|
package/lib/fsm.js
CHANGED
|
@@ -17,10 +17,14 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
17
17
|
};
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.useService = exports.useMachine = void 0;
|
|
20
|
-
var react_1 = require("react");
|
|
21
20
|
var fsm_1 = require("@xstate/fsm");
|
|
22
|
-
var
|
|
21
|
+
var react_1 = require("react");
|
|
22
|
+
var use_isomorphic_layout_effect_1 = require("use-isomorphic-layout-effect");
|
|
23
|
+
var with_selector_1 = require("use-sync-external-store/shim/with-selector");
|
|
23
24
|
var useConstant_1 = require("./useConstant");
|
|
25
|
+
function identity(a) {
|
|
26
|
+
return a;
|
|
27
|
+
}
|
|
24
28
|
var getServiceState = function (service) {
|
|
25
29
|
var currentValue;
|
|
26
30
|
service
|
|
@@ -31,48 +35,53 @@ var getServiceState = function (service) {
|
|
|
31
35
|
return currentValue;
|
|
32
36
|
};
|
|
33
37
|
function useMachine(stateMachine, options) {
|
|
38
|
+
var persistedStateRef = (0, react_1.useRef)();
|
|
34
39
|
if (process.env.NODE_ENV !== 'production') {
|
|
35
|
-
var _a = __read(react_1.useState(stateMachine), 1), initialMachine = _a[0];
|
|
40
|
+
var _a = __read((0, react_1.useState)(stateMachine), 1), initialMachine = _a[0];
|
|
36
41
|
if (stateMachine !== initialMachine) {
|
|
37
42
|
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' +
|
|
38
43
|
'Please make sure that you pass the same Machine as argument each time.');
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
var _b = __read((0, useConstant_1.default)(function () {
|
|
47
|
+
var queue = [];
|
|
48
|
+
var service = (0, fsm_1.interpret)((0, fsm_1.createMachine)(stateMachine.config, options ? options : stateMachine._options));
|
|
49
|
+
var send = service.send;
|
|
50
|
+
service.send = function (event) {
|
|
51
|
+
if (service.status === fsm_1.InterpreterStatus.NotStarted) {
|
|
52
|
+
queue.push(event);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
send(event);
|
|
56
|
+
persistedStateRef.current = service.state;
|
|
57
|
+
};
|
|
58
|
+
return [service, queue];
|
|
59
|
+
}), 2), service = _b[0], queue = _b[1];
|
|
60
|
+
(0, use_isomorphic_layout_effect_1.default)(function () {
|
|
46
61
|
if (options) {
|
|
47
62
|
service._machine._options = options;
|
|
48
63
|
}
|
|
49
64
|
});
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
var useServiceResult = useService(service);
|
|
66
|
+
(0, react_1.useEffect)(function () {
|
|
67
|
+
service.start(persistedStateRef.current);
|
|
68
|
+
queue.forEach(service.send);
|
|
69
|
+
persistedStateRef.current = service.state;
|
|
52
70
|
return function () {
|
|
53
71
|
service.stop();
|
|
54
72
|
};
|
|
55
73
|
}, []);
|
|
56
|
-
return
|
|
74
|
+
return useServiceResult;
|
|
57
75
|
}
|
|
58
76
|
exports.useMachine = useMachine;
|
|
77
|
+
var isEqual = function (_prevState, nextState) { return nextState.changed === false; };
|
|
59
78
|
function useService(service) {
|
|
60
|
-
var
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
subscribe: function (callback) {
|
|
65
|
-
var unsubscribe = service.subscribe(function (state) {
|
|
66
|
-
if (state.changed !== false) {
|
|
67
|
-
currentState = state;
|
|
68
|
-
callback();
|
|
69
|
-
}
|
|
70
|
-
}).unsubscribe;
|
|
71
|
-
return unsubscribe;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
79
|
+
var getSnapshot = (0, react_1.useCallback)(function () { return getServiceState(service); }, [service]);
|
|
80
|
+
var subscribe = (0, react_1.useCallback)(function (handleStoreChange) {
|
|
81
|
+
var unsubscribe = service.subscribe(handleStoreChange).unsubscribe;
|
|
82
|
+
return unsubscribe;
|
|
74
83
|
}, [service]);
|
|
75
|
-
var
|
|
76
|
-
return [
|
|
84
|
+
var storeSnapshot = (0, with_selector_1.useSyncExternalStoreWithSelector)(subscribe, getSnapshot, getSnapshot, identity, isEqual);
|
|
85
|
+
return [storeSnapshot, service.send, service];
|
|
77
86
|
}
|
|
78
87
|
exports.useService = useService;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { useMachine
|
|
2
|
-
export { useService } from './useService';
|
|
1
|
+
export { useMachine } from './useMachine';
|
|
3
2
|
export { useActor } from './useActor';
|
|
4
3
|
export { useInterpret } from './useInterpret';
|
|
5
4
|
export { useSelector } from './useSelector';
|
package/lib/index.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useSpawn = exports.useSelector = exports.useInterpret = exports.useActor = exports.
|
|
3
|
+
exports.useSpawn = exports.useSelector = exports.useInterpret = exports.useActor = exports.useMachine = void 0;
|
|
4
4
|
var useMachine_1 = require("./useMachine");
|
|
5
5
|
Object.defineProperty(exports, "useMachine", { enumerable: true, get: function () { return useMachine_1.useMachine; } });
|
|
6
|
-
Object.defineProperty(exports, "asEffect", { enumerable: true, get: function () { return useMachine_1.asEffect; } });
|
|
7
|
-
Object.defineProperty(exports, "asLayoutEffect", { enumerable: true, get: function () { return useMachine_1.asLayoutEffect; } });
|
|
8
|
-
var useService_1 = require("./useService");
|
|
9
|
-
Object.defineProperty(exports, "useService", { enumerable: true, get: function () { return useService_1.useService; } });
|
|
10
6
|
var useActor_1 = require("./useActor");
|
|
11
7
|
Object.defineProperty(exports, "useActor", { enumerable: true, get: function () { return useActor_1.useActor; } });
|
|
12
8
|
var useInterpret_1 = require("./useInterpret");
|
package/lib/types.d.ts
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EventObject, StateConfig } from 'xstate';
|
|
2
2
|
export declare type MaybeLazy<T> = T | (() => T);
|
|
3
3
|
export declare type NoInfer<T> = [T][T extends any ? 0 : any];
|
|
4
4
|
export declare type Prop<T, K> = K extends keyof T ? T[K] : never;
|
|
5
|
-
export declare enum ReactEffectType {
|
|
6
|
-
Effect = 1,
|
|
7
|
-
LayoutEffect = 2
|
|
8
|
-
}
|
|
9
|
-
export interface ReactActionFunction<TContext, TEvent extends EventObject> {
|
|
10
|
-
(context: TContext, event: TEvent, meta: ActionMeta<TContext, TEvent>): () => void;
|
|
11
|
-
__effect: ReactEffectType;
|
|
12
|
-
}
|
|
13
|
-
export interface ReactActionObject<TContext, TEvent extends EventObject> extends ActionObject<TContext, TEvent> {
|
|
14
|
-
exec: ReactActionFunction<TContext, TEvent>;
|
|
15
|
-
}
|
|
16
5
|
export interface UseMachineOptions<TContext, TEvent extends EventObject> {
|
|
17
6
|
/**
|
|
18
7
|
* If provided, will be merged with machine's `context`.
|
|
@@ -24,8 +13,4 @@ export interface UseMachineOptions<TContext, TEvent extends EventObject> {
|
|
|
24
13
|
*/
|
|
25
14
|
state?: StateConfig<TContext, TEvent>;
|
|
26
15
|
}
|
|
27
|
-
export declare type ActionStateTuple<TContext, TEvent extends EventObject> = [
|
|
28
|
-
ReactActionObject<TContext, TEvent>,
|
|
29
|
-
State<TContext, TEvent>
|
|
30
|
-
];
|
|
31
16
|
//# sourceMappingURL=types.d.ts.map
|
package/lib/types.js
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ReactEffectType = void 0;
|
|
4
|
-
var ReactEffectType;
|
|
5
|
-
(function (ReactEffectType) {
|
|
6
|
-
ReactEffectType[ReactEffectType["Effect"] = 1] = "Effect";
|
|
7
|
-
ReactEffectType[ReactEffectType["LayoutEffect"] = 2] = "LayoutEffect";
|
|
8
|
-
})(ReactEffectType = exports.ReactEffectType || (exports.ReactEffectType = {}));
|