@xstate/react 1.5.1 → 1.6.3

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/es/useActor.js CHANGED
@@ -38,7 +38,15 @@ export function useActor(actorRef, getSnapshot) {
38
38
  var actorRefRef = useRef(actorRef);
39
39
  var deferredEventsRef = useRef([]);
40
40
  var _a = __read(useState(function () { return getSnapshot(actorRef); }), 2), current = _a[0], setCurrent = _a[1];
41
- var send = useConstant(function () { return function (event) {
41
+ var send = useConstant(function () { return function () {
42
+ var args = [];
43
+ for (var _i = 0; _i < arguments.length; _i++) {
44
+ args[_i] = arguments[_i];
45
+ }
46
+ var event = args[0];
47
+ if (process.env.NODE_ENV !== 'production' && args.length > 1) {
48
+ console.warn("Unexpected payload: ".concat(JSON.stringify(args[1]), ". Only a single event object can be sent to actor send() functions."));
49
+ }
42
50
  var currentActorRef = actorRefRef.current;
43
51
  // If the previous actor is a deferred actor,
44
52
  // queue the events so that they can be replayed
@@ -62,7 +62,7 @@ export function useInterpret(getMachine, options, observerOrListener) {
62
62
  if (process.env.NODE_ENV !== 'production' &&
63
63
  typeof getMachine !== 'function') {
64
64
  var _a = __read(useState(machine), 1), initialMachine = _a[0];
65
- if (machine !== initialMachine) {
65
+ if (getMachine !== initialMachine) {
66
66
  console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' +
67
67
  'Please make sure that you pass the same Machine as argument each time.');
68
68
  }
@@ -77,7 +77,7 @@ export function useInterpret(getMachine, options, observerOrListener) {
77
77
  services: services,
78
78
  delays: delays
79
79
  };
80
- var machineWithConfig = machine.withConfig(machineConfig, __assign(__assign({}, machine.context), context));
80
+ var machineWithConfig = machine.withConfig(machineConfig, function () { return (__assign(__assign({}, machine.context), context)); });
81
81
  return interpret(machineWithConfig, __assign({ deferEvents: true }, interpreterOptions));
82
82
  });
83
83
  useIsomorphicLayoutEffect(function () {
@@ -95,15 +95,16 @@ export function useInterpret(getMachine, options, observerOrListener) {
95
95
  service.stop();
96
96
  };
97
97
  }, []);
98
- // Make sure actions and services are kept updated when they change.
98
+ // Make sure options are kept updated when they change.
99
99
  // This mutation assignment is safe because the service instance is only used
100
100
  // in one place -- this hook's caller.
101
101
  useIsomorphicLayoutEffect(function () {
102
102
  Object.assign(service.machine.options.actions, actions);
103
- }, [actions]);
104
- useIsomorphicLayoutEffect(function () {
103
+ Object.assign(service.machine.options.guards, guards);
104
+ Object.assign(service.machine.options.activities, activities);
105
105
  Object.assign(service.machine.options.services, services);
106
- }, [services]);
106
+ Object.assign(service.machine.options.delays, delays);
107
+ }, [actions, guards, activities, services, delays]);
107
108
  useReactEffectActions(service);
108
109
  return service;
109
110
  }
package/es/useMachine.js CHANGED
@@ -14,10 +14,14 @@ var __read = (this && this.__read) || function (o, n) {
14
14
  }
15
15
  return ar;
16
16
  };
17
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
18
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
19
- to[j] = from[i];
20
- return to;
17
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
18
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
19
+ if (ar || !(i in from)) {
20
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
21
+ ar[i] = from[i];
22
+ }
23
+ }
24
+ return to.concat(ar || Array.prototype.slice.call(from));
21
25
  };
22
26
  import { useCallback, useState } from 'react';
23
27
  import { State } from 'xstate';
@@ -31,11 +35,11 @@ function createReactActionFunction(exec, tag) {
31
35
  }
32
36
  // don't execute; just return
33
37
  return function () {
34
- return exec.apply(void 0, __spreadArray([], __read(args)));
38
+ return exec.apply(void 0, __spreadArray([], __read(args), false));
35
39
  };
36
40
  };
37
41
  Object.defineProperties(effectExec, {
38
- name: { value: "effect:" + exec.name },
42
+ name: { value: "effect:".concat(exec.name) },
39
43
  __effect: { value: tag }
40
44
  });
41
45
  return effectExec;
@@ -14,10 +14,14 @@ var __read = (this && this.__read) || function (o, n) {
14
14
  }
15
15
  return ar;
16
16
  };
17
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
18
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
19
- to[j] = from[i];
20
- return to;
17
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
18
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
19
+ if (ar || !(i in from)) {
20
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
21
+ ar[i] = from[i];
22
+ }
23
+ }
24
+ return to.concat(ar || Array.prototype.slice.call(from));
21
25
  };
22
26
  import { useEffect, useRef } from 'react';
23
27
  import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
@@ -46,8 +50,8 @@ export function useReactEffectActions(service) {
46
50
  var _c = __read(partition(reactEffectActions, function (action) {
47
51
  return action.exec.__effect === ReactEffectType.Effect;
48
52
  }), 2), effectActions = _c[0], layoutEffectActions = _c[1];
49
- (_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; }))));
50
- (_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; }))));
53
+ (_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })), false));
54
+ (_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })), false));
51
55
  }
52
56
  });
53
57
  return function () {
package/es/useSelector.js CHANGED
@@ -1,20 +1,6 @@
1
- var __read = (this && this.__read) || function (o, n) {
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 { useEffect, useRef, useState } from 'react';
1
+ import { useMemo, useRef } from 'react';
2
+ import { useSubscription } from 'use-subscription';
3
+ import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';
18
4
  import { isActorWithState } from './useActor';
19
5
  import { getServiceSnapshot } from './useService';
20
6
  function isService(actor) {
@@ -31,22 +17,54 @@ var defaultGetSnapshot = function (a) {
31
17
  export function useSelector(actor, selector, compare, getSnapshot) {
32
18
  if (compare === void 0) { compare = defaultCompare; }
33
19
  if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; }
34
- var _a = __read(useState(function () { return selector(getSnapshot(actor)); }), 2), selected = _a[0], setSelected = _a[1];
35
- var selectedRef = useRef(selected);
36
- useEffect(function () {
37
- var updateSelectedIfChanged = function (nextSelected) {
38
- if (!compare(selectedRef.current, nextSelected)) {
39
- setSelected(nextSelected);
40
- selectedRef.current = nextSelected;
20
+ var latestSelectorRef = useRef(selector);
21
+ var subscription = useMemo(function () {
22
+ var snapshot = getSnapshot(actor);
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
+ };
41
45
  }
42
46
  };
43
- var initialSelected = selector(getSnapshot(actor));
44
- updateSelectedIfChanged(initialSelected);
45
- var sub = actor.subscribe(function (emitted) {
46
- var nextSelected = selector(emitted);
47
- updateSelectedIfChanged(nextSelected);
48
- });
49
- return function () { return sub.unsubscribe(); };
50
- }, [selector, compare]);
51
- return selected;
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)
50
+ }, [actor]);
51
+ var currentSelected = useSubscription(subscription);
52
+ var currentChanged = false;
53
+ if (latestSelectorRef.current !== selector) {
54
+ var selected = selector(subscription.getSnapshot());
55
+ if (!compare(currentSelected, selected)) {
56
+ currentChanged = true;
57
+ currentSelected = selected;
58
+ }
59
+ }
60
+ useIsomorphicLayoutEffect(function () {
61
+ latestSelectorRef.current = selector;
62
+ // this condition should not be required, but setState bailouts are currently buggy: https://github.com/facebook/react/issues/22654
63
+ if (currentChanged) {
64
+ // required so we don't cause a rerender by setting state (this could create infinite rerendering loop with inline selectors)
65
+ // 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
66
+ subscription.setCurrentValue(currentSelected);
67
+ }
68
+ });
69
+ return currentSelected;
52
70
  }
package/lib/fsm.js CHANGED
@@ -32,22 +32,22 @@ var getServiceState = function (service) {
32
32
  };
33
33
  function useMachine(stateMachine, options) {
34
34
  if (process.env.NODE_ENV !== 'production') {
35
- var _a = __read(react_1.useState(stateMachine), 1), initialMachine = _a[0];
35
+ var _a = __read((0, react_1.useState)(stateMachine), 1), initialMachine = _a[0];
36
36
  if (stateMachine !== initialMachine) {
37
37
  console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' +
38
38
  'Please make sure that you pass the same Machine as argument each time.');
39
39
  }
40
40
  }
41
- var service = useConstant_1.default(function () {
42
- return fsm_1.interpret(fsm_1.createMachine(stateMachine.config, options ? options : stateMachine._options)).start();
41
+ var service = (0, useConstant_1.default)(function () {
42
+ return (0, fsm_1.interpret)((0, fsm_1.createMachine)(stateMachine.config, options ? options : stateMachine._options)).start();
43
43
  });
44
- var _b = __read(react_1.useState(function () { return getServiceState(service); }), 2), state = _b[0], setState = _b[1];
45
- react_1.useEffect(function () {
44
+ var _b = __read((0, react_1.useState)(function () { return getServiceState(service); }), 2), state = _b[0], setState = _b[1];
45
+ (0, react_1.useEffect)(function () {
46
46
  if (options) {
47
47
  service._machine._options = options;
48
48
  }
49
49
  });
50
- react_1.useEffect(function () {
50
+ (0, react_1.useEffect)(function () {
51
51
  service.subscribe(setState);
52
52
  return function () {
53
53
  service.stop();
@@ -57,7 +57,7 @@ function useMachine(stateMachine, options) {
57
57
  }
58
58
  exports.useMachine = useMachine;
59
59
  function useService(service) {
60
- var subscription = react_1.useMemo(function () {
60
+ var subscription = (0, react_1.useMemo)(function () {
61
61
  var currentState = getServiceState(service);
62
62
  return {
63
63
  getCurrentValue: function () { return currentState; },
@@ -72,7 +72,7 @@ function useService(service) {
72
72
  }
73
73
  };
74
74
  }, [service]);
75
- var state = use_subscription_1.useSubscription(subscription);
75
+ var state = (0, use_subscription_1.useSubscription)(subscription);
76
76
  return [state, service.send, service];
77
77
  }
78
78
  exports.useService = useService;
package/lib/useActor.js CHANGED
@@ -39,10 +39,18 @@ function defaultGetSnapshot(actorRef) {
39
39
  }
40
40
  function useActor(actorRef, getSnapshot) {
41
41
  if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; }
42
- var actorRefRef = react_1.useRef(actorRef);
43
- var deferredEventsRef = react_1.useRef([]);
44
- var _a = __read(react_1.useState(function () { return getSnapshot(actorRef); }), 2), current = _a[0], setCurrent = _a[1];
45
- var send = useConstant_1.default(function () { return function (event) {
42
+ var actorRefRef = (0, react_1.useRef)(actorRef);
43
+ var deferredEventsRef = (0, react_1.useRef)([]);
44
+ var _a = __read((0, react_1.useState)(function () { return getSnapshot(actorRef); }), 2), current = _a[0], setCurrent = _a[1];
45
+ var send = (0, useConstant_1.default)(function () { return function () {
46
+ var args = [];
47
+ for (var _i = 0; _i < arguments.length; _i++) {
48
+ args[_i] = arguments[_i];
49
+ }
50
+ var event = args[0];
51
+ if (process.env.NODE_ENV !== 'production' && args.length > 1) {
52
+ console.warn("Unexpected payload: ".concat(JSON.stringify(args[1]), ". Only a single event object can be sent to actor send() functions."));
53
+ }
46
54
  var currentActorRef = actorRefRef.current;
47
55
  // If the previous actor is a deferred actor,
48
56
  // queue the events so that they can be replayed
@@ -54,7 +62,7 @@ function useActor(actorRef, getSnapshot) {
54
62
  currentActorRef.send(event);
55
63
  }
56
64
  }; });
57
- use_isomorphic_layout_effect_1.default(function () {
65
+ (0, use_isomorphic_layout_effect_1.default)(function () {
58
66
  actorRefRef.current = actorRef;
59
67
  setCurrent(getSnapshot(actorRef));
60
68
  var subscription = actorRef.subscribe({
@@ -59,19 +59,19 @@ function toObserver(nextHandler, errorHandler, completionHandler) {
59
59
  }
60
60
  function useInterpret(getMachine, options, observerOrListener) {
61
61
  if (options === void 0) { options = {}; }
62
- var machine = useConstant_1.default(function () {
62
+ var machine = (0, useConstant_1.default)(function () {
63
63
  return typeof getMachine === 'function' ? getMachine() : getMachine;
64
64
  });
65
65
  if (process.env.NODE_ENV !== 'production' &&
66
66
  typeof getMachine !== 'function') {
67
- var _a = __read(react_1.useState(machine), 1), initialMachine = _a[0];
68
- if (machine !== initialMachine) {
67
+ var _a = __read((0, react_1.useState)(machine), 1), initialMachine = _a[0];
68
+ if (getMachine !== initialMachine) {
69
69
  console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' +
70
70
  'Please make sure that you pass the same Machine as argument each time.');
71
71
  }
72
72
  }
73
73
  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"]);
74
- var service = useConstant_1.default(function () {
74
+ var service = (0, useConstant_1.default)(function () {
75
75
  var machineConfig = {
76
76
  context: context,
77
77
  guards: guards,
@@ -80,10 +80,10 @@ function useInterpret(getMachine, options, observerOrListener) {
80
80
  services: services,
81
81
  delays: delays
82
82
  };
83
- var machineWithConfig = machine.withConfig(machineConfig, __assign(__assign({}, machine.context), context));
84
- return xstate_1.interpret(machineWithConfig, __assign({ deferEvents: true }, interpreterOptions));
83
+ var machineWithConfig = machine.withConfig(machineConfig, function () { return (__assign(__assign({}, machine.context), context)); });
84
+ return (0, xstate_1.interpret)(machineWithConfig, __assign({ deferEvents: true }, interpreterOptions));
85
85
  });
86
- use_isomorphic_layout_effect_1.default(function () {
86
+ (0, use_isomorphic_layout_effect_1.default)(function () {
87
87
  var sub;
88
88
  if (observerOrListener) {
89
89
  sub = service.subscribe(toObserver(observerOrListener));
@@ -92,22 +92,23 @@ function useInterpret(getMachine, options, observerOrListener) {
92
92
  sub === null || sub === void 0 ? void 0 : sub.unsubscribe();
93
93
  };
94
94
  }, [observerOrListener]);
95
- use_isomorphic_layout_effect_1.default(function () {
95
+ (0, use_isomorphic_layout_effect_1.default)(function () {
96
96
  service.start(rehydratedState ? xstate_1.State.create(rehydratedState) : undefined);
97
97
  return function () {
98
98
  service.stop();
99
99
  };
100
100
  }, []);
101
- // Make sure actions and services are kept updated when they change.
101
+ // Make sure options are kept updated when they change.
102
102
  // This mutation assignment is safe because the service instance is only used
103
103
  // in one place -- this hook's caller.
104
- use_isomorphic_layout_effect_1.default(function () {
104
+ (0, use_isomorphic_layout_effect_1.default)(function () {
105
105
  Object.assign(service.machine.options.actions, actions);
106
- }, [actions]);
107
- use_isomorphic_layout_effect_1.default(function () {
106
+ Object.assign(service.machine.options.guards, guards);
107
+ Object.assign(service.machine.options.activities, activities);
108
108
  Object.assign(service.machine.options.services, services);
109
- }, [services]);
110
- useReactEffectActions_1.useReactEffectActions(service);
109
+ Object.assign(service.machine.options.delays, delays);
110
+ }, [actions, guards, activities, services, delays]);
111
+ (0, useReactEffectActions_1.useReactEffectActions)(service);
111
112
  return service;
112
113
  }
113
114
  exports.useInterpret = useInterpret;
package/lib/useMachine.js CHANGED
@@ -15,10 +15,14 @@ var __read = (this && this.__read) || function (o, n) {
15
15
  }
16
16
  return ar;
17
17
  };
18
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
19
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
20
- to[j] = from[i];
21
- return to;
18
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
+ if (ar || !(i in from)) {
21
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
+ ar[i] = from[i];
23
+ }
24
+ }
25
+ return to.concat(ar || Array.prototype.slice.call(from));
22
26
  };
23
27
  Object.defineProperty(exports, "__esModule", { value: true });
24
28
  exports.useMachine = exports.asLayoutEffect = exports.asEffect = void 0;
@@ -34,11 +38,11 @@ function createReactActionFunction(exec, tag) {
34
38
  }
35
39
  // don't execute; just return
36
40
  return function () {
37
- return exec.apply(void 0, __spreadArray([], __read(args)));
41
+ return exec.apply(void 0, __spreadArray([], __read(args), false));
38
42
  };
39
43
  };
40
44
  Object.defineProperties(effectExec, {
41
- name: { value: "effect:" + exec.name },
45
+ name: { value: "effect:".concat(exec.name) },
42
46
  __effect: { value: tag }
43
47
  });
44
48
  return effectExec;
@@ -53,7 +57,7 @@ function asLayoutEffect(exec) {
53
57
  exports.asLayoutEffect = asLayoutEffect;
54
58
  function useMachine(getMachine, options) {
55
59
  if (options === void 0) { options = {}; }
56
- var listener = react_1.useCallback(function (nextState) {
60
+ var listener = (0, react_1.useCallback)(function (nextState) {
57
61
  // Only change the current state if:
58
62
  // - the incoming state is the "live" initial state (since it might have new actors)
59
63
  // - OR the incoming state actually changed.
@@ -65,8 +69,8 @@ function useMachine(getMachine, options) {
65
69
  setState(nextState);
66
70
  }
67
71
  }, []);
68
- var service = useInterpret_1.useInterpret(getMachine, options, listener);
69
- var _a = __read(react_1.useState(function () {
72
+ var service = (0, useInterpret_1.useInterpret)(getMachine, options, listener);
73
+ var _a = __read((0, react_1.useState)(function () {
70
74
  var initialState = service.machine.initialState;
71
75
  return (options.state
72
76
  ? xstate_1.State.create(options.state)
@@ -15,10 +15,14 @@ var __read = (this && this.__read) || function (o, n) {
15
15
  }
16
16
  return ar;
17
17
  };
18
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
19
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
20
- to[j] = from[i];
21
- return to;
18
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
+ if (ar || !(i in from)) {
21
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
+ ar[i] = from[i];
23
+ }
24
+ }
25
+ return to.concat(ar || Array.prototype.slice.call(from));
22
26
  };
23
27
  Object.defineProperty(exports, "__esModule", { value: true });
24
28
  exports.useReactEffectActions = void 0;
@@ -36,9 +40,9 @@ function executeEffect(action, state) {
36
40
  originalExec();
37
41
  }
38
42
  function useReactEffectActions(service) {
39
- var effectActionsRef = react_1.useRef([]);
40
- var layoutEffectActionsRef = react_1.useRef([]);
41
- use_isomorphic_layout_effect_1.default(function () {
43
+ var effectActionsRef = (0, react_1.useRef)([]);
44
+ var layoutEffectActionsRef = (0, react_1.useRef)([]);
45
+ (0, use_isomorphic_layout_effect_1.default)(function () {
42
46
  var sub = service.subscribe(function (currentState) {
43
47
  var _a, _b;
44
48
  if (currentState.actions.length) {
@@ -46,11 +50,11 @@ function useReactEffectActions(service) {
46
50
  return (typeof action.exec === 'function' &&
47
51
  '__effect' in action.exec);
48
52
  });
49
- var _c = __read(utils_1.partition(reactEffectActions, function (action) {
53
+ var _c = __read((0, utils_1.partition)(reactEffectActions, function (action) {
50
54
  return action.exec.__effect === types_1.ReactEffectType.Effect;
51
55
  }), 2), effectActions = _c[0], layoutEffectActions = _c[1];
52
- (_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; }))));
53
- (_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; }))));
56
+ (_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })), false));
57
+ (_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })), false));
54
58
  }
55
59
  });
56
60
  return function () {
@@ -60,13 +64,13 @@ function useReactEffectActions(service) {
60
64
  // this is somewhat weird - this should always be flushed within useLayoutEffect
61
65
  // but we don't want to receive warnings about useLayoutEffect being used on the server
62
66
  // so we have to use `useIsomorphicLayoutEffect` to silence those warnings
63
- use_isomorphic_layout_effect_1.default(function () {
67
+ (0, use_isomorphic_layout_effect_1.default)(function () {
64
68
  while (layoutEffectActionsRef.current.length) {
65
69
  var _a = __read(layoutEffectActionsRef.current.shift(), 2), layoutEffectAction = _a[0], effectState = _a[1];
66
70
  executeEffect(layoutEffectAction, effectState);
67
71
  }
68
72
  }); // https://github.com/davidkpiano/xstate/pull/1202#discussion_r429677773
69
- react_1.useEffect(function () {
73
+ (0, react_1.useEffect)(function () {
70
74
  while (effectActionsRef.current.length) {
71
75
  var _a = __read(effectActionsRef.current.shift(), 2), effectAction = _a[0], effectState = _a[1];
72
76
  executeEffect(effectAction, effectState);
@@ -1,23 +1,9 @@
1
1
  "use strict";
2
- var __read = (this && this.__read) || function (o, n) {
3
- var m = typeof Symbol === "function" && o[Symbol.iterator];
4
- if (!m) return o;
5
- var i = m.call(o), r, ar = [], e;
6
- try {
7
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
- }
9
- catch (error) { e = { error: error }; }
10
- finally {
11
- try {
12
- if (r && !r.done && (m = i["return"])) m.call(i);
13
- }
14
- finally { if (e) throw e.error; }
15
- }
16
- return ar;
17
- };
18
2
  Object.defineProperty(exports, "__esModule", { value: true });
19
3
  exports.useSelector = void 0;
20
4
  var react_1 = require("react");
5
+ var use_subscription_1 = require("use-subscription");
6
+ var use_isomorphic_layout_effect_1 = require("use-isomorphic-layout-effect");
21
7
  var useActor_1 = require("./useActor");
22
8
  var useService_1 = require("./useService");
23
9
  function isService(actor) {
@@ -26,31 +12,63 @@ function isService(actor) {
26
12
  var defaultCompare = function (a, b) { return a === b; };
27
13
  var defaultGetSnapshot = function (a) {
28
14
  return isService(a)
29
- ? useService_1.getServiceSnapshot(a)
30
- : useActor_1.isActorWithState(a)
15
+ ? (0, useService_1.getServiceSnapshot)(a)
16
+ : (0, useActor_1.isActorWithState)(a)
31
17
  ? a.state
32
18
  : undefined;
33
19
  };
34
20
  function useSelector(actor, selector, compare, getSnapshot) {
35
21
  if (compare === void 0) { compare = defaultCompare; }
36
22
  if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; }
37
- var _a = __read(react_1.useState(function () { return selector(getSnapshot(actor)); }), 2), selected = _a[0], setSelected = _a[1];
38
- var selectedRef = react_1.useRef(selected);
39
- react_1.useEffect(function () {
40
- var updateSelectedIfChanged = function (nextSelected) {
41
- if (!compare(selectedRef.current, nextSelected)) {
42
- setSelected(nextSelected);
43
- selectedRef.current = nextSelected;
23
+ var latestSelectorRef = (0, react_1.useRef)(selector);
24
+ var subscription = (0, react_1.useMemo)(function () {
25
+ var snapshot = getSnapshot(actor);
26
+ var current = selector(snapshot);
27
+ var notifySubscriber;
28
+ return {
29
+ getSnapshot: function () { return snapshot; },
30
+ getCurrentValue: function () { return current; },
31
+ setCurrentValue: function (newCurrent) {
32
+ current = newCurrent;
33
+ notifySubscriber === null || notifySubscriber === void 0 ? void 0 : notifySubscriber();
34
+ },
35
+ subscribe: function (callback) {
36
+ notifySubscriber = callback;
37
+ var sub = actor.subscribe(function (emitted) {
38
+ snapshot = emitted;
39
+ var next = latestSelectorRef.current(emitted);
40
+ if (!compare(current, next)) {
41
+ current = next;
42
+ callback();
43
+ }
44
+ });
45
+ return function () {
46
+ sub.unsubscribe();
47
+ };
44
48
  }
45
49
  };
46
- var initialSelected = selector(getSnapshot(actor));
47
- updateSelectedIfChanged(initialSelected);
48
- var sub = actor.subscribe(function (emitted) {
49
- var nextSelected = selector(emitted);
50
- updateSelectedIfChanged(nextSelected);
51
- });
52
- return function () { return sub.unsubscribe(); };
53
- }, [selector, compare]);
54
- return selected;
50
+ // intentionally omit `getSnapshot` and `compare`
51
+ // - `getSnapshot`: it is only supposed to read the "initial" snapshot of an actor
52
+ // - `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)
53
+ }, [actor]);
54
+ var currentSelected = (0, use_subscription_1.useSubscription)(subscription);
55
+ var currentChanged = false;
56
+ if (latestSelectorRef.current !== selector) {
57
+ var selected = selector(subscription.getSnapshot());
58
+ if (!compare(currentSelected, selected)) {
59
+ currentChanged = true;
60
+ currentSelected = selected;
61
+ }
62
+ }
63
+ (0, use_isomorphic_layout_effect_1.default)(function () {
64
+ latestSelectorRef.current = selector;
65
+ // this condition should not be required, but setState bailouts are currently buggy: https://github.com/facebook/react/issues/22654
66
+ if (currentChanged) {
67
+ // required so we don't cause a rerender by setting state (this could create infinite rerendering loop with inline selectors)
68
+ // 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
69
+ subscription.setCurrentValue(currentSelected);
70
+ }
71
+ });
72
+ return currentSelected;
55
73
  }
56
74
  exports.useSelector = useSelector;
package/lib/useService.js CHANGED
@@ -35,7 +35,7 @@ function useService(service) {
35
35
  if (process.env.NODE_ENV !== 'production' && !('machine' in service)) {
36
36
  throw new Error("Attempted to use an actor-like object instead of a service in the useService() hook. Please use the useActor() hook instead.");
37
37
  }
38
- var _a = __read(useActor_1.useActor(service), 1), state = _a[0];
38
+ var _a = __read((0, useActor_1.useActor)(service), 1), state = _a[0];
39
39
  return [state, service.send];
40
40
  }
41
41
  exports.useService = useService;
package/lib/useSpawn.js CHANGED
@@ -11,8 +11,8 @@ var useConstant_1 = require("./useConstant");
11
11
  * @returns An ActorRef with the specified `behavior`
12
12
  */
13
13
  function useSpawn(behavior) {
14
- var actorRef = useConstant_1.default(function () {
15
- return behaviors_1.spawnBehavior(behavior);
14
+ var actorRef = (0, useConstant_1.default)(function () {
15
+ return (0, behaviors_1.spawnBehavior)(behavior);
16
16
  });
17
17
  return actorRef;
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xstate/react",
3
- "version": "1.5.1",
3
+ "version": "1.6.3",
4
4
  "description": "XState tools for React",
5
5
  "keywords": [
6
6
  "state",
@@ -39,7 +39,7 @@
39
39
  "clean": "rm -rf dist lib tsconfig.tsbuildinfo",
40
40
  "build": "tsc && tsc --outDir es --module es2015 && rollup -c",
41
41
  "test": "jest",
42
- "prepublish": "npm run build && npm run test"
42
+ "prepublish": "npm run build"
43
43
  },
44
44
  "bugs": {
45
45
  "url": "https://github.com/davidkpiano/xstate/issues"
@@ -78,9 +78,9 @@
78
78
  "rollup": "^2.35.1",
79
79
  "rollup-plugin-replace": "^2.2.0",
80
80
  "rollup-plugin-terser": "^5.1.2",
81
- "rollup-plugin-typescript2": "^0.29.0",
81
+ "rollup-plugin-typescript2": "^0.30.0",
82
82
  "ts-jest": "^26.5.6",
83
- "typescript": "^4.3.2",
83
+ "typescript": "^4.5.2",
84
84
  "xstate": "*"
85
85
  }
86
86
  }