@xstate/react
Advanced tools
Comparing version 2.0.0-pr2674-20219612435 to 2.0.0
100
CHANGELOG.md
# Changelog | ||
## 2.0.0-pr2674-20219612435 | ||
## 2.0.0 | ||
### Major Changes | ||
- e5a8b8dff: author: @Andarist | ||
author: @mattpocock | ||
- [#2674](https://github.com/statelyai/xstate/pull/2674) [`e5a8b8dff`](https://github.com/statelyai/xstate/commit/e5a8b8dffb88cffbdca26683099ffdf5f1b01c8d) Thanks [@Andarist](https://github.com/Andarist), [@mattpocock](https://github.com/mattpocock)! - To avoid breaking any consumers and to leverage the newly introduced typegen support, the major version of this package had to be bumped. While you can still use it with older versions of TS, the typegen support in this package requires TS version 4.0 or greater. | ||
To avoid breaking any consumers and to leverage the newly introduced typegen support the major version of this package had to be bumped. While you can still use it with older versions of TS the typegen support in this package required at least TS 4.0. | ||
When using hooks from `@xstate/react` it's recommended to skip providing explicit generics to them. Note that that generics list has changed since v1 and we now only accept a single generic, `TMachine`. | ||
* [#2674](https://github.com/statelyai/xstate/pull/2674) [`ab919d300`](https://github.com/statelyai/xstate/commit/ab919d300f6d2b78871d3399ec58a697c4268d9b) Thanks [@Andarist](https://github.com/Andarist)! - Removed already deprecated `useService` from `@xstate/react`. You can replace its usage with `useActor`. | ||
### Patch Changes | ||
- Updated dependencies [1ff4f7976] | ||
- Updated dependencies [1cd26811c] | ||
- xstate@4.26.0-pr2674-20219612435 | ||
- [#2957](https://github.com/statelyai/xstate/pull/2957) [`8550ddda7`](https://github.com/statelyai/xstate/commit/8550ddda73e2ad291e19173d7fa8d13e3336fbb9) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The repository links have been updated from `github.com/davidkpiano` to `github.com/statelyai`. | ||
## 1.6.3 | ||
### Patch Changes | ||
- [#2767](https://github.com/statelyai/xstate/pull/2767) [`c1503b121`](https://github.com/statelyai/xstate/commit/c1503b1219d995ebf0f45de46036c5a1d7e6442f) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an over-rendering issue in the `useSelector`. | ||
## 1.6.2 | ||
### Patch Changes | ||
- [#2736](https://github.com/statelyai/xstate/pull/2736) [`2246ae051`](https://github.com/statelyai/xstate/commit/2246ae051663f261b4750d7adba57f008ec28f1d) Thanks [@Andarist](https://github.com/Andarist), [@davidkpiano](https://github.com/statelyai), [@VanTanev](https://github.com/VanTanev)! - The `useSelector(...)` hook now works as expected when the `actor` passed in changes. The hook will properly subscribe to the new `actor` and select the desired value. See [#2702](https://github.com/statelyai/xstate/issues/2702) | ||
* [#2685](https://github.com/statelyai/xstate/pull/2685) [`469268d39`](https://github.com/statelyai/xstate/commit/469268d39fbc23996599773adfc4ca824b48585f) Thanks [@farskid](https://github.com/farskid), [@Andarist](https://github.com/Andarist)! - Fixed a regression with a development-only warning not being shown when a machine reference is updated during the hook lifecycle. This usually happens when machine options are dependent on external values and they're passed via `withConfig`. | ||
```js | ||
const machine = createMachine({ | ||
initial: 'foo', | ||
context: { id: 1 }, | ||
states: { | ||
foo: { | ||
on: { | ||
CHECK: { | ||
target: 'bar', | ||
cond: 'hasOverflown' | ||
} | ||
} | ||
}, | ||
bar: {} | ||
} | ||
}); | ||
const [id, setId] = useState(1); | ||
const [current, send] = useMachine( | ||
machine.withConfig({ | ||
guards: { | ||
hasOverflown: () => id > 1 // id is a reference to an outside value | ||
} | ||
}) | ||
); | ||
// later when id updates | ||
setId(2); | ||
// Now the reference passed to `useMachine` (the result of `machine.withConfig`) is updated but the interpreted machine stays the same. So the guard is still the previous one that got passed to the `useMachine` initially, and it closes over the stale `id`. | ||
``` | ||
## 1.6.1 | ||
@@ -79,3 +123,3 @@ | ||
- [`453acacb`](https://github.com/statelyai/xstate/commit/453acacbec364531a2851f183c3ab446d7db0e84) [#2389](https://github.com/statelyai/xstate/pull/2389) Thanks [@davidkpiano](https://github.com/davidkpiano)! - An internal issue where the `spawnBehavior` import for the `useSpawn(...)` hook was broken internally has been fixed. | ||
- [`453acacb`](https://github.com/statelyai/xstate/commit/453acacbec364531a2851f183c3ab446d7db0e84) [#2389](https://github.com/statelyai/xstate/pull/2389) Thanks [@davidkpiano](https://github.com/statelyai)! - An internal issue where the `spawnBehavior` import for the `useSpawn(...)` hook was broken internally has been fixed. | ||
@@ -86,3 +130,3 @@ ## 1.5.0 | ||
- [`432b60f7`](https://github.com/statelyai/xstate/commit/432b60f7bcbcee9510e0d86311abbfd75b1a674e) [#2280](https://github.com/statelyai/xstate/pull/2280) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Just like `useInvoke(...)`, other types of actors can now be spawned from _behaviors_ using `useSpawn(...)`: | ||
- [`432b60f7`](https://github.com/statelyai/xstate/commit/432b60f7bcbcee9510e0d86311abbfd75b1a674e) [#2280](https://github.com/statelyai/xstate/pull/2280) Thanks [@davidkpiano](https://github.com/statelyai)! - Just like `useInvoke(...)`, other types of actors can now be spawned from _behaviors_ using `useSpawn(...)`: | ||
@@ -141,3 +185,3 @@ ```tsx | ||
- [`849ec56c`](https://github.com/davidkpiano/xstate/commit/849ec56c2a9db34e65a30af94e68a7a7a50b4158) [#2286](https://github.com/davidkpiano/xstate/pull/2286) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The `useService(...)` hook will be deprecated, since services are also actors. In future versions, the `useActor(...)` hook should be used instead: | ||
- [`849ec56c`](https://github.com/statelyai/xstate/commit/849ec56c2a9db34e65a30af94e68a7a7a50b4158) [#2286](https://github.com/statelyai/xstate/pull/2286) Thanks [@davidkpiano](https://github.com/statelyai)! - The `useService(...)` hook will be deprecated, since services are also actors. In future versions, the `useActor(...)` hook should be used instead: | ||
@@ -151,3 +195,3 @@ ```diff | ||
- [`ea3aaffb`](https://github.com/davidkpiano/xstate/commit/ea3aaffb906b34a42bb2736c7b91d54ffe9ed882) [#2326](https://github.com/davidkpiano/xstate/pull/2326) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The `send` type returned in the tuple from `useActor(someService)` was an incorrect `never` type; this has been fixed. | ||
- [`ea3aaffb`](https://github.com/statelyai/xstate/commit/ea3aaffb906b34a42bb2736c7b91d54ffe9ed882) [#2326](https://github.com/statelyai/xstate/pull/2326) Thanks [@davidkpiano](https://github.com/statelyai)! - The `send` type returned in the tuple from `useActor(someService)` was an incorrect `never` type; this has been fixed. | ||
@@ -158,3 +202,3 @@ ## 1.3.4 | ||
- [`aa3c2991`](https://github.com/davidkpiano/xstate/commit/aa3c29916b7382fbcf1a3efb183ca1e8eb625480) [#2223](https://github.com/davidkpiano/xstate/pull/2223) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Support for actor refs with the `.getSnapshot()` method (added for spawned actors in XState version 4.19) is now supported in the `useActor(...)` hook. | ||
- [`aa3c2991`](https://github.com/statelyai/xstate/commit/aa3c29916b7382fbcf1a3efb183ca1e8eb625480) [#2223](https://github.com/statelyai/xstate/pull/2223) Thanks [@davidkpiano](https://github.com/statelyai)! - Support for actor refs with the `.getSnapshot()` method (added for spawned actors in XState version 4.19) is now supported in the `useActor(...)` hook. | ||
@@ -165,3 +209,3 @@ ## 1.3.3 | ||
- [`27e7242c`](https://github.com/davidkpiano/xstate/commit/27e7242c24146de85cf618a658b400a3241fa7d7) [#2112](https://github.com/davidkpiano/xstate/pull/2112) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The `executeEffect` function is no longer exported (was meant to be internal and is useless as a public function anyway). This also fixes a circular dependency issue. | ||
- [`27e7242c`](https://github.com/statelyai/xstate/commit/27e7242c24146de85cf618a658b400a3241fa7d7) [#2112](https://github.com/statelyai/xstate/pull/2112) Thanks [@davidkpiano](https://github.com/statelyai)! - The `executeEffect` function is no longer exported (was meant to be internal and is useless as a public function anyway). This also fixes a circular dependency issue. | ||
@@ -172,3 +216,3 @@ ## 1.3.2 | ||
- [`bb5e81ea`](https://github.com/davidkpiano/xstate/commit/bb5e81eaa1ecba1fd54a7677ce9eaee9bd695964) [#2050](https://github.com/davidkpiano/xstate/pull/2050) Thanks [@theKashey](https://github.com/theKashey)! - Added an explicit entrypoint for `@xstate/react/fsm` which you can use instead of `@xstate/react/lib/fsm`. This is the only specifier that will be supported in the future - the other one will be dropped in the next major version. | ||
- [`bb5e81ea`](https://github.com/statelyai/xstate/commit/bb5e81eaa1ecba1fd54a7677ce9eaee9bd695964) [#2050](https://github.com/statelyai/xstate/pull/2050) Thanks [@theKashey](https://github.com/theKashey)! - Added an explicit entrypoint for `@xstate/react/fsm` which you can use instead of `@xstate/react/lib/fsm`. This is the only specifier that will be supported in the future - the other one will be dropped in the next major version. | ||
@@ -184,5 +228,5 @@ ```diff | ||
- [`b076b253`](https://github.com/davidkpiano/xstate/commit/b076b25364224874f62e8065892be40dfbb28030) [#1947](https://github.com/davidkpiano/xstate/pull/1947) Thanks [@lukekarrys](https://github.com/lukekarrys)! - Fix typing of the service returned from the fsm useMachine hook by passing it Typestate | ||
- [`b076b253`](https://github.com/statelyai/xstate/commit/b076b25364224874f62e8065892be40dfbb28030) [#1947](https://github.com/statelyai/xstate/pull/1947) Thanks [@lukekarrys](https://github.com/lukekarrys)! - Fix typing of the service returned from the fsm useMachine hook by passing it Typestate | ||
* [`9b5dc784`](https://github.com/davidkpiano/xstate/commit/9b5dc7843c44f50bcca0ffccb843b3d50cef6ddc) [#1950](https://github.com/davidkpiano/xstate/pull/1950) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with `toObserver` being internally imported from `xstate/lib/utils` which has broken UMD build and the declared peer dep contract. | ||
* [`9b5dc784`](https://github.com/statelyai/xstate/commit/9b5dc7843c44f50bcca0ffccb843b3d50cef6ddc) [#1950](https://github.com/statelyai/xstate/pull/1950) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with `toObserver` being internally imported from `xstate/lib/utils` which has broken UMD build and the declared peer dep contract. | ||
@@ -193,3 +237,3 @@ ## 1.3.0 | ||
- [`577ae023`](https://github.com/davidkpiano/xstate/commit/577ae02384926b49e876011c4393f212b49066f8) [#1915](https://github.com/davidkpiano/xstate/pull/1915) Thanks [@davidkpiano](https://github.com/davidkpiano)! - New hook: `useInterpret(machine)`, which is a low-level hook that interprets the `machine` and returns the `service`: | ||
- [`577ae023`](https://github.com/statelyai/xstate/commit/577ae02384926b49e876011c4393f212b49066f8) [#1915](https://github.com/statelyai/xstate/pull/1915) Thanks [@davidkpiano](https://github.com/statelyai)! - New hook: `useInterpret(machine)`, which is a low-level hook that interprets the `machine` and returns the `service`: | ||
@@ -207,3 +251,3 @@ ```js | ||
* [`577ae023`](https://github.com/davidkpiano/xstate/commit/577ae02384926b49e876011c4393f212b49066f8) [#1915](https://github.com/davidkpiano/xstate/pull/1915) Thanks [@davidkpiano](https://github.com/davidkpiano)! - New hook: `useSelector(actor, selector)`, which subscribes to `actor` and returns the selected state derived from `selector(snapshot)`: | ||
* [`577ae023`](https://github.com/statelyai/xstate/commit/577ae02384926b49e876011c4393f212b49066f8) [#1915](https://github.com/statelyai/xstate/pull/1915) Thanks [@davidkpiano](https://github.com/statelyai)! - New hook: `useSelector(actor, selector)`, which subscribes to `actor` and returns the selected state derived from `selector(snapshot)`: | ||
@@ -224,3 +268,3 @@ ```js | ||
- [`4b31cefb`](https://github.com/davidkpiano/xstate/commit/4b31cefb3d3497e5515314046639df7e27dbe9e8) [#1780](https://github.com/davidkpiano/xstate/pull/1780) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with some external packages not being bundled correctly into the UMD bundles. | ||
- [`4b31cefb`](https://github.com/statelyai/xstate/commit/4b31cefb3d3497e5515314046639df7e27dbe9e8) [#1780](https://github.com/statelyai/xstate/pull/1780) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with some external packages not being bundled correctly into the UMD bundles. | ||
@@ -231,3 +275,3 @@ ## 1.2.1 | ||
- [`a16a5f2f`](https://github.com/davidkpiano/xstate/commit/a16a5f2ff5ba9d4d7834ec3ca2d0adecf5d6a870) [#1756](https://github.com/davidkpiano/xstate/pull/1756) Thanks [@dimitardanailov](https://github.com/dimitardanailov)! - Fixed an issue with `process` references not being removed correctly from the UMD bundles. | ||
- [`a16a5f2f`](https://github.com/statelyai/xstate/commit/a16a5f2ff5ba9d4d7834ec3ca2d0adecf5d6a870) [#1756](https://github.com/statelyai/xstate/pull/1756) Thanks [@dimitardanailov](https://github.com/dimitardanailov)! - Fixed an issue with `process` references not being removed correctly from the UMD bundles. | ||
@@ -238,3 +282,3 @@ ## 1.2.0 | ||
- [`dd98296e`](https://github.com/davidkpiano/xstate/commit/dd98296e9fcbae905da2395e67e876e28be7c774) [#1738](https://github.com/davidkpiano/xstate/pull/1738) Thanks [@dimitardanailov](https://github.com/dimitardanailov)! - Added UMD bundle. | ||
- [`dd98296e`](https://github.com/statelyai/xstate/commit/dd98296e9fcbae905da2395e67e876e28be7c774) [#1738](https://github.com/statelyai/xstate/pull/1738) Thanks [@dimitardanailov](https://github.com/dimitardanailov)! - Added UMD bundle. | ||
@@ -245,3 +289,3 @@ ## 1.1.0 | ||
- [`89f9c27c`](https://github.com/davidkpiano/xstate/commit/89f9c27c453dc56bdfdf49c8ea1f0f87ff1f9b67) [#1622](https://github.com/davidkpiano/xstate/pull/1622) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Spawned/invoked actors and interpreters are now typed as extending `ActorRef` rather than `Actor` or `Interpreter`. This unification of types should make it more straightforward to provide actor types in React: | ||
- [`89f9c27c`](https://github.com/statelyai/xstate/commit/89f9c27c453dc56bdfdf49c8ea1f0f87ff1f9b67) [#1622](https://github.com/statelyai/xstate/pull/1622) Thanks [@davidkpiano](https://github.com/statelyai)! - Spawned/invoked actors and interpreters are now typed as extending `ActorRef` rather than `Actor` or `Interpreter`. This unification of types should make it more straightforward to provide actor types in React: | ||
@@ -288,3 +332,3 @@ ```ts | ||
- [`27db2950`](https://github.com/davidkpiano/xstate/commit/27db295064d42cacb89ff10d55f39eb7609148e1) [#1636](https://github.com/davidkpiano/xstate/pull/1636) Thanks [@Andarist](https://github.com/Andarist)! - Allow React 17 in the specified peer dependency range. | ||
- [`27db2950`](https://github.com/statelyai/xstate/commit/27db295064d42cacb89ff10d55f39eb7609148e1) [#1636](https://github.com/statelyai/xstate/pull/1636) Thanks [@Andarist](https://github.com/Andarist)! - Allow React 17 in the specified peer dependency range. | ||
@@ -295,5 +339,5 @@ ## 1.0.2 | ||
- [`c7927083`](https://github.com/davidkpiano/xstate/commit/c7927083a651e3c51952ade2ffda793df0391bf6) [#1516](https://github.com/davidkpiano/xstate/pull/1516) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The `send` function returned from the `useService()` now can take two arguments (an event type and payload), to match the behavior of `@xstate/react` version 0.x. | ||
- [`c7927083`](https://github.com/statelyai/xstate/commit/c7927083a651e3c51952ade2ffda793df0391bf6) [#1516](https://github.com/statelyai/xstate/pull/1516) Thanks [@davidkpiano](https://github.com/statelyai)! - The `send` function returned from the `useService()` now can take two arguments (an event type and payload), to match the behavior of `@xstate/react` version 0.x. | ||
* [`db77623a`](https://github.com/davidkpiano/xstate/commit/db77623a48955d762cffa9b624f438220add5eed) [#1516](https://github.com/davidkpiano/xstate/pull/1516) Thanks [@davidkpiano](https://github.com/davidkpiano)! - The `send` value returned from the `useService()` hook will now accept a payload, which matches the signature of the `send` value returned from the `useMachine()` hook: | ||
* [`db77623a`](https://github.com/statelyai/xstate/commit/db77623a48955d762cffa9b624f438220add5eed) [#1516](https://github.com/statelyai/xstate/pull/1516) Thanks [@davidkpiano](https://github.com/statelyai)! - The `send` value returned from the `useService()` hook will now accept a payload, which matches the signature of the `send` value returned from the `useMachine()` hook: | ||
@@ -312,5 +356,5 @@ ```js | ||
- [`93f6db02`](https://github.com/davidkpiano/xstate/commit/93f6db02a2d56ec997198ddef0af3d7730bb79bb) [#1594](https://github.com/davidkpiano/xstate/pull/1594) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with internal `setState` in `useService` being called with 2 arguments instead of 1. | ||
- [`93f6db02`](https://github.com/statelyai/xstate/commit/93f6db02a2d56ec997198ddef0af3d7730bb79bb) [#1594](https://github.com/statelyai/xstate/pull/1594) Thanks [@Andarist](https://github.com/Andarist)! - Fixed an issue with internal `setState` in `useService` being called with 2 arguments instead of 1. | ||
* [`72b0880e`](https://github.com/davidkpiano/xstate/commit/72b0880e6444ae009adca72088872bb5c0760ce3) [#1504](https://github.com/davidkpiano/xstate/pull/1504) Thanks [@Andarist](https://github.com/Andarist)! - Fixed issue with `useService` returning an initial state for services in their final states. | ||
* [`72b0880e`](https://github.com/statelyai/xstate/commit/72b0880e6444ae009adca72088872bb5c0760ce3) [#1504](https://github.com/statelyai/xstate/pull/1504) Thanks [@Andarist](https://github.com/Andarist)! - Fixed issue with `useService` returning an initial state for services in their final states. | ||
@@ -321,3 +365,3 @@ ## 1.0.1 | ||
- [`c0bd0407`](https://github.com/davidkpiano/xstate/commit/c0bd040767dcac20ed690e49a8725b4f1011dd5d) [#1493](https://github.com/davidkpiano/xstate/pull/1493) Thanks [@davidkpiano](https://github.com/davidkpiano)! - There will now be a descriptive error when trying to use an actor-like object in the `useService()` hook, where `useActor()` should be preferred: | ||
- [`c0bd0407`](https://github.com/statelyai/xstate/commit/c0bd040767dcac20ed690e49a8725b4f1011dd5d) [#1493](https://github.com/statelyai/xstate/pull/1493) Thanks [@davidkpiano](https://github.com/statelyai)! - There will now be a descriptive error when trying to use an actor-like object in the `useService()` hook, where `useActor()` should be preferred: | ||
@@ -324,0 +368,0 @@ > Attempted to use an actor-like object instead of a service in the useService() hook. Please use the useActor() hook instead. |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("react"),require("xstate"),require("xstate/lib/behaviors")):"function"==typeof define&&define.amd?define(["exports","react","xstate","xstate/lib/behaviors"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).XStateReact={},t.React,t.XState,t.behaviors)}(this,(function(t,e,n,r){"use strict"; | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("xstate"),require("xstate/lib/behaviors")):"function"==typeof define&&define.amd?define(["exports","react","xstate","xstate/lib/behaviors"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).XStateReact={},e.React,e.XState,e.behaviors)}(this,(function(e,t,n,r){"use strict";function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o,i=u(t),c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var u in t=arguments[n])Object.prototype.hasOwnProperty.call(t,u)&&(e[u]=t[u]);return e}).apply(this,arguments)}; | ||
/*! ***************************************************************************** | ||
@@ -15,2 +15,15 @@ Copyright (c) Microsoft Corporation. | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */var u,i=function(){return(i=Object.assign||function(t){for(var e,n=1,r=arguments.length;n<r;n++)for(var u in e=arguments[n])Object.prototype.hasOwnProperty.call(e,u)&&(t[u]=e[u]);return t}).apply(this,arguments)};function o(t,e){var n={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var u=0;for(r=Object.getOwnPropertySymbols(t);u<r.length;u++)e.indexOf(r[u])<0&&Object.prototype.propertyIsEnumerable.call(t,r[u])&&(n[r[u]]=t[r[u]])}return n}function c(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator];if(!n)return t;var r,u,i=n.call(t),o=[];try{for(;(void 0===e||e-- >0)&&!(r=i.next()).done;)o.push(r.value)}catch(t){u={error:t}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(u)throw u.error}}return o}function a(t,e){for(var n=0,r=e.length,u=t.length;n<r;n++,u++)t[u]=e[n];return t}!function(t){t[t.Effect=1]="Effect",t[t.LayoutEffect=2]="LayoutEffect"}(u||(u={}));var f=e.useLayoutEffect;function s(t){var n=e.useRef();return n.current||(n.current={v:t()}),n.current.v}function l(t,e){var n,r,u=c([[],[]],2),i=u[0],o=u[1];try{for(var a=function(t){var e="function"==typeof Symbol&&Symbol.iterator,n=e&&t[e],r=0;if(n)return n.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}(t),f=a.next();!f.done;f=a.next()){var s=f.value;e(s)?i.push(s):o.push(s)}}catch(t){n={error:t}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(n)throw n.error}}return[i,o]}function v(t,e){(0,t.exec)(e.context,e._event.data,{action:t,state:e,_event:e._event})()}function p(t){var n=e.useRef([]),r=e.useRef([]);f((function(){var e=t.subscribe((function(t){var e,i;if(t.actions.length){var o=c(l(t.actions.filter((function(t){return"function"==typeof t.exec&&"__effect"in t.exec})),(function(t){return t.exec.__effect===u.Effect})),2),f=o[0],s=o[1];(e=n.current).push.apply(e,a([],c(f.map((function(e){return[e,t]}))))),(i=r.current).push.apply(i,a([],c(s.map((function(e){return[e,t]})))))}}));return function(){e.unsubscribe()}}),[]),f((function(){for(;r.current.length;){var t=c(r.current.shift(),2);v(t[0],t[1])}})),e.useEffect((function(){for(;n.current.length;){var t=c(n.current.shift(),2);v(t[0],t[1])}}))}function d(t,e,n){if("object"==typeof t)return t;var r=function(){};return{next:t,error:e||r,complete:n||r}}function h(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var r=c(t,3),u=r[0],a=r[1],l=void 0===a?{}:a,v=r[2],h=s((function(){return"function"==typeof u?u():u})),b=l.context,y=l.guards,g=l.actions,m=l.services,x=l.delays,O=l.state,S=o(l,["context","guards","actions","services","delays","state"]),j=l.activities,E=s((function(){var t={context:b,guards:y,actions:g,activities:j,services:m,delays:x},e=h.withConfig(t,(function(){return i(i({},h.context),b)}));return n.interpret(e,i({deferEvents:!0},S))}));return f((function(){var t;return v&&(t=E.subscribe(d(v))),function(){null==t||t.unsubscribe()}}),[v]),f((function(){return E.start(O?n.State.create(O):void 0),function(){E.stop()}}),[]),f((function(){Object.assign(E.machine.options.actions,g),Object.assign(E.machine.options.guards,y),Object.assign(E.machine.options.activities,j),Object.assign(E.machine.options.services,m),Object.assign(E.machine.options.delays,x)}),[g,y,j,m,x]),p(E),E}function b(t,e){var n=function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return function(){return t.apply(void 0,a([],c(e)))}};return Object.defineProperties(n,{name:{value:"effect:"+t.name},__effect:{value:e}}),n}function y(t){return"state"in t}function g(t){return"deferred"in t}var m=function(){};function x(t){return"getSnapshot"in t?t.getSnapshot():y(t)?t.state:void 0}function O(t,n){void 0===n&&(n=x);var r=e.useRef(t),u=e.useRef([]),i=c(e.useState((function(){return n(t)})),2),o=i[0],a=i[1],l=s((function(){return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t[0],i=r.current;g(i)&&i.deferred?u.current.push(n):i.send(n)}}));return f((function(){r.current=t,a(n(t));for(var e=t.subscribe({next:function(t){return a(t)},error:m,complete:m});u.current.length>0;){var i=u.current.shift();t.send(i)}return function(){e.unsubscribe()}}),[t]),[o,l]}var S=function(t,e){return t===e},j=function(t){return"state"in(n=t)&&"machine"in n?0!==("status"in(e=t)?e.status:e._status)?e.state:e.machine.initialState:y(t)?t.state:void 0;var e,n};t.asEffect=function(t){return b(t,u.Effect)},t.asLayoutEffect=function(t){return b(t,u.LayoutEffect)},t.useActor=O,t.useInterpret=h,t.useMachine=function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var u=c(t,2),i=u[0],o=u[1],a=void 0===o?{}:o,f=e.useCallback((function(t){var e=void 0===t.changed&&Object.keys(t.children).length;(t.changed||e)&&p(t)}),[]),s=h(i,a,f),l=c(e.useState((function(){var t=s.machine.initialState;return a.state?n.State.create(a.state):t})),2),v=l[0],p=l[1];return[v,s.send,s]},t.useSelector=function(t,n,r,u){void 0===r&&(r=S),void 0===u&&(u=j);var i=c(e.useState((function(){return n(u(t))})),2),o=i[0],a=i[1],f=e.useRef(o);return e.useEffect((function(){var e=function(t){r(f.current,t)||(a(t),f.current=t)},i=n(u(t));e(i);var o=t.subscribe((function(t){var r=n(t);e(r)}));return function(){return o.unsubscribe()}}),[n,r]),o},t.useService=function(t){return[c(O(t),1)[0],t.send]},t.useSpawn=function(t){return s((function(){return r.spawnBehavior(t)}))},Object.defineProperty(t,"__esModule",{value:!0})})); | ||
***************************************************************************** */function a(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var u=0;for(r=Object.getOwnPropertySymbols(e);u<r.length;u++)t.indexOf(r[u])<0&&Object.prototype.propertyIsEnumerable.call(e,r[u])&&(n[r[u]]=e[r[u]])}return n}function f(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,u,o=n.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)i.push(r.value)}catch(e){u={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(u)throw u.error}}return i}function s(e,t,n){if(n||2===arguments.length)for(var r,u=0,o=t.length;u<o;u++)!r&&u in t||(r||(r=Array.prototype.slice.call(t,0,u)),r[u]=t[u]);return e.concat(r||Array.prototype.slice.call(t))}!function(e){e[e.Effect=1]="Effect",e[e.LayoutEffect=2]="LayoutEffect"}(o||(o={}));var l=t.useLayoutEffect;function v(e){var n=t.useRef();return n.current||(n.current={v:e()}),n.current.v}function p(e,t){var n,r,u=f([[],[]],2),o=u[0],i=u[1];try{for(var c=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(e),a=c.next();!a.done;a=c.next()){var s=a.value;t(s)?o.push(s):i.push(s)}}catch(e){n={error:e}}finally{try{a&&!a.done&&(r=c.return)&&r.call(c)}finally{if(n)throw n.error}}return[o,i]}function b(e,t){(0,e.exec)(t.context,t._event.data,{action:e,state:t,_event:t._event})()}function h(e){var n=t.useRef([]),r=t.useRef([]);l((function(){var t=e.subscribe((function(e){var t,u;if(e.actions.length){var i=f(p(e.actions.filter((function(e){return"function"==typeof e.exec&&"__effect"in e.exec})),(function(e){return e.exec.__effect===o.Effect})),2),c=i[0],a=i[1];(t=n.current).push.apply(t,s([],f(c.map((function(t){return[t,e]}))),!1)),(u=r.current).push.apply(u,s([],f(a.map((function(t){return[t,e]}))),!1))}}));return function(){t.unsubscribe()}}),[]),l((function(){for(;r.current.length;){var e=f(r.current.shift(),2);b(e[0],e[1])}})),t.useEffect((function(){for(;n.current.length;){var e=f(n.current.shift(),2);b(e[0],e[1])}}))}function y(e,t,n){if("object"==typeof e)return e;var r=function(){};return{next:e,error:t||r,complete:n||r}}function d(e){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];var u=f(t,2),o=u[0],i=void 0===o?{}:o,s=u[1],p=v((function(){return"function"==typeof e?e():e})),b=i.context,d=i.guards,g=i.actions,O=i.services,j=i.delays,m=i.state,x=a(i,["context","guards","actions","services","delays","state"]),S=i.activities,w=v((function(){var e={context:b,guards:d,actions:g,activities:S,services:O,delays:j},t=p.withConfig(e,(function(){return c(c({},p.context),b)}));return n.interpret(t,c({deferEvents:!0},x))}));return l((function(){var e;return s&&(e=w.subscribe(y(s))),function(){null==e||e.unsubscribe()}}),[s]),l((function(){return w.start(m?n.State.create(m):void 0),function(){w.stop()}}),[]),l((function(){Object.assign(w.machine.options.actions,g),Object.assign(w.machine.options.guards,d),Object.assign(w.machine.options.activities,S),Object.assign(w.machine.options.services,O),Object.assign(w.machine.options.delays,j)}),[g,d,S,O,j]),h(w),w}function g(e,t){var n=function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return function(){return e.apply(void 0,s([],f(t),!1))}};return Object.defineProperties(n,{name:{value:"effect:".concat(e.name)},__effect:{value:t}}),n}function O(e){return"state"in e}function j(e){return"deferred"in e}var m=function(){};function x(e){return"getSnapshot"in e?e.getSnapshot():O(e)?e.state:void 0}function S(e){var t={exports:{}};return e(t,t.exports),t.exports | ||
/* | ||
object-assign | ||
(c) Sindre Sorhus | ||
@license MIT | ||
*/}var w=Object.getOwnPropertySymbols,E=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;function _(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}var P=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,r,u=_(e),o=1;o<arguments.length;o++){for(var i in n=Object(arguments[o]))E.call(n,i)&&(u[i]=n[i]);if(w){r=w(n);for(var c=0;c<r.length;c++)C.call(n,r[c])&&(u[r[c]]=n[r[c]])}}return u},V={useSubscription:function(e){var t=e.getCurrentValue,n=e.subscribe,r=i.default.useState((function(){return{getCurrentValue:t,subscribe:n,value:t()}}));e=r[0];var u=r[1];return r=e.value,e.getCurrentValue===t&&e.subscribe===n||(r=t(),u({getCurrentValue:t,subscribe:n,value:r})),i.default.useDebugValue(r),i.default.useEffect((function(){function e(){if(!r){var e=t();u((function(r){return r.getCurrentValue!==t||r.subscribe!==n||r.value===e?r:P({},r,{value:e})}))}}var r=!1,o=n(e);return e(),function(){r=!0,o()}}),[t,n]),r}},R=(S((function(e,t){})),S((function(e){e.exports=V}))); | ||
/** @license React vundefined | ||
* use-subscription.production.min.js | ||
* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/var k=function(e,t){return e===t},q=function(e){return"state"in(n=e)&&"machine"in n?0!==(t=e).status?t.state:t.machine.initialState:O(e)?e.state:void 0;var t,n};e.asEffect=function(e){return g(e,o.Effect)},e.asLayoutEffect=function(e){return g(e,o.LayoutEffect)},e.useActor=function(e,n){void 0===n&&(n=x);var r=t.useRef(e),u=t.useRef([]),o=f(t.useState((function(){return n(e)})),2),i=o[0],c=o[1],a=v((function(){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=e[0],o=r.current;j(o)&&o.deferred?u.current.push(n):o.send(n)}}));return l((function(){r.current=e,c(n(e));for(var t=e.subscribe({next:function(e){return c(e)},error:m,complete:m});u.current.length>0;){var o=u.current.shift();e.send(o)}return function(){t.unsubscribe()}}),[e]),[i,a]},e.useInterpret=d,e.useMachine=function(e){for(var r=[],u=1;u<arguments.length;u++)r[u-1]=arguments[u];var o=f(r,1),i=o[0],c=void 0===i?{}:i,a=t.useCallback((function(e){var t=void 0===e.changed&&Object.keys(e.children).length;(e.changed||t)&&p(e)}),[]),s=d(e,c,a),l=f(t.useState((function(){var e=s.machine.initialState;return c.state?n.State.create(c.state):e})),2),v=l[0],p=l[1];return[v,s.send,s]},e.useSelector=function(e,n,r,u){void 0===r&&(r=k),void 0===u&&(u=q);var o=t.useRef(n),i=t.useMemo((function(){var t,i=u(e),c=n(i);return{getSnapshot:function(){return i},getCurrentValue:function(){return c},setCurrentValue:function(e){c=e,null==t||t()},subscribe:function(n){t=n;var u=e.subscribe((function(e){i=e;var t=o.current(e);r(c,t)||(c=t,n())}));return function(){u.unsubscribe()}}}}),[e]),c=R.useSubscription(i),a=!1;if(o.current!==n){var f=n(i.getSnapshot());r(c,f)||(a=!0,c=f)}return l((function(){o.current=n,a&&i.setCurrentValue(c)})),c},e.useSpawn=function(e){return v((function(){return r.spawnBehavior(e)}))},Object.defineProperty(e,"__esModule",{value:!0})})); |
export { useMachine, asEffect, asLayoutEffect } from './useMachine'; | ||
export { useService } from './useService'; | ||
export { useActor } from './useActor'; | ||
@@ -4,0 +3,0 @@ export { useInterpret } from './useInterpret'; |
export { useMachine, asEffect, asLayoutEffect } from './useMachine'; | ||
export { useService } from './useService'; | ||
export { useActor } from './useActor'; | ||
@@ -4,0 +3,0 @@ export { useInterpret } from './useInterpret'; |
import { ActionMeta, ActionObject, EventObject, State, StateConfig } from 'xstate'; | ||
export declare type MaybeLazy<T> = T | (() => T); | ||
export declare type NoInfer<T> = [T][T extends any ? 0 : any]; | ||
export declare type Prop<T, K> = K extends keyof T ? T[K] : never; | ||
export declare enum ReactEffectType { | ||
@@ -5,0 +6,0 @@ Effect = 1, |
@@ -48,3 +48,3 @@ var __read = (this && this.__read) || function (o, n) { | ||
if (process.env.NODE_ENV !== 'production' && args.length > 1) { | ||
console.warn("Unexpected payload: " + JSON.stringify(args[1]) + ". Only a single event object can be sent to actor send() functions."); | ||
console.warn("Unexpected payload: ".concat(JSON.stringify(args[1]), ". Only a single event object can be sent to actor send() functions.")); | ||
} | ||
@@ -51,0 +51,0 @@ var currentActorRef = actorRefRef.current; |
@@ -1,16 +0,13 @@ | ||
import { EventObject, StateMachine, State, Interpreter, InterpreterOptions, Typestate, Observer, TypegenConstraint, TypegenDisabled, AreAllImplementationsAssumedToBeProvided, MaybeTypegenMachineOptions, BaseActionObject } from 'xstate'; | ||
import { MaybeLazy, NoInfer } from './types'; | ||
import { AreAllImplementationsAssumedToBeProvided, InternalMachineOptions, InterpreterFrom, InterpreterOptions, Observer, State, StateMachine } from 'xstate'; | ||
import { MaybeLazy } from './types'; | ||
import { UseMachineOptions } from './useMachine'; | ||
export declare function useInterpret<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = { | ||
value: any; | ||
context: TContext; | ||
}, TResolvedTypesMeta extends TypegenConstraint = TypegenDisabled>(...[getMachine, options, observerOrListener]: AreAllImplementationsAssumedToBeProvided<TResolvedTypesMeta> extends false ? [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta, true>, | ||
observerOrListener?: Observer<State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>> | ((value: State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>) => void) | ||
declare type RestParams<TMachine extends StateMachine<any, any, any, any, any, any, any>> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [ | ||
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true>, | ||
observerOrListener?: Observer<State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>> | ((value: State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>) => void) | ||
] : [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options?: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta>, | ||
observerOrListener?: Observer<State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>> | ((value: State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>) => void) | ||
]): Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta>; | ||
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']>, | ||
observerOrListener?: Observer<State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>> | ((value: State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>) => void) | ||
]; | ||
export declare function useInterpret<TMachine extends StateMachine<any, any, any, any, any, any, any>>(getMachine: MaybeLazy<TMachine>, ...[options, observerOrListener]: RestParams<TMachine>): InterpreterFrom<TMachine>; | ||
export {}; | ||
//# sourceMappingURL=useInterpret.d.ts.map |
@@ -57,8 +57,8 @@ var __assign = (this && this.__assign) || function () { | ||
} | ||
export function useInterpret() { | ||
export function useInterpret(getMachine) { | ||
var _a = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
_a[_i] = arguments[_i]; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
_a[_i - 1] = arguments[_i]; | ||
} | ||
var _b = __read(_a, 3), getMachine = _b[0], _c = _b[1], options = _c === void 0 ? {} : _c, observerOrListener = _b[2]; | ||
var _b = __read(_a, 2), _c = _b[0], options = _c === void 0 ? {} : _c, observerOrListener = _b[1]; | ||
var machine = useConstant(function () { | ||
@@ -70,3 +70,3 @@ return typeof getMachine === 'function' ? getMachine() : getMachine; | ||
var _d = __read(useState(machine), 1), initialMachine = _d[0]; | ||
if (machine !== initialMachine) { | ||
if (getMachine !== initialMachine) { | ||
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' + | ||
@@ -73,0 +73,0 @@ 'Please make sure that you pass the same Machine as argument each time.'); |
@@ -1,3 +0,3 @@ | ||
import { ActionFunction, AreAllImplementationsAssumedToBeProvided, BaseActionObject, EventObject, Interpreter, InterpreterOptions, MaybeTypegenMachineOptions, State, StateConfig, StateMachine, TypegenConstraint, TypegenDisabled, Typestate } from 'xstate'; | ||
import { MaybeLazy, NoInfer, ReactActionFunction } from './types'; | ||
import { ActionFunction, AreAllImplementationsAssumedToBeProvided, EventObject, InternalMachineOptions, InterpreterFrom, InterpreterOptions, StateConfig, StateFrom, StateMachine } from 'xstate'; | ||
import { MaybeLazy, Prop, ReactActionFunction } from './types'; | ||
export declare function asEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>; | ||
@@ -16,16 +16,10 @@ export declare function asLayoutEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>; | ||
} | ||
export declare function useMachine<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = { | ||
value: any; | ||
context: TContext; | ||
}, TResolvedTypesMeta extends TypegenConstraint = TypegenDisabled>(...[getMachine, options]: AreAllImplementationsAssumedToBeProvided<TResolvedTypesMeta> extends false ? [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta, true> | ||
declare type RestParams<TMachine extends StateMachine<any, any, any, any, any, any, any>> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [ | ||
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true> | ||
] : [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options?: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta> | ||
]): [ | ||
State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>, | ||
Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta>['send'], | ||
Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta> | ||
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']> | ||
]; | ||
declare type UseMachineReturn<TMachine extends StateMachine<any, any, any, any, any, any, any>, TInterpreter = InterpreterFrom<TMachine>> = [StateFrom<TMachine>, Prop<TInterpreter, 'send'>, TInterpreter]; | ||
export declare function useMachine<TMachine extends StateMachine<any, any, any, any, any, any, any>>(getMachine: MaybeLazy<TMachine>, ...[options]: RestParams<TMachine>): UseMachineReturn<TMachine>; | ||
export {}; | ||
//# sourceMappingURL=useMachine.d.ts.map |
@@ -17,6 +17,10 @@ var __read = (this && this.__read) || function (o, n) { | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -35,7 +39,7 @@ import { useCallback, useState } from 'react'; | ||
return function () { | ||
return exec.apply(void 0, __spreadArray([], __read(args))); | ||
return exec.apply(void 0, __spreadArray([], __read(args), false)); | ||
}; | ||
}; | ||
Object.defineProperties(effectExec, { | ||
name: { value: "effect:" + exec.name }, | ||
name: { value: "effect:".concat(exec.name) }, | ||
__effect: { value: tag } | ||
@@ -51,8 +55,8 @@ }); | ||
} | ||
export function useMachine() { | ||
export function useMachine(getMachine) { | ||
var _a = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
_a[_i] = arguments[_i]; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
_a[_i - 1] = arguments[_i]; | ||
} | ||
var _b = __read(_a, 2), getMachine = _b[0], _c = _b[1], options = _c === void 0 ? {} : _c; | ||
var _b = __read(_a, 1), _c = _b[0], options = _c === void 0 ? {} : _c; | ||
var listener = useCallback(function (nextState) { | ||
@@ -64,4 +68,3 @@ // Only change the current state if: | ||
// The "live" initial state will have .changed === undefined. | ||
var initialStateChanged = nextState.changed === undefined && | ||
Object.keys(nextState.children).length; | ||
var initialStateChanged = nextState.changed === undefined && Object.keys(nextState.children).length; | ||
if (nextState.changed || initialStateChanged) { | ||
@@ -68,0 +71,0 @@ setState(nextState); |
@@ -17,6 +17,10 @@ var __read = (this && this.__read) || function (o, n) { | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -50,4 +54,4 @@ import { useEffect, useRef } from 'react'; | ||
}), 2), effectActions = _c[0], layoutEffectActions = _c[1]; | ||
(_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })))); | ||
(_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })))); | ||
(_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })), false)); | ||
(_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })), false)); | ||
} | ||
@@ -67,3 +71,3 @@ }); | ||
} | ||
}); // https://github.com/davidkpiano/xstate/pull/1202#discussion_r429677773 | ||
}); // https://github.com/statelyai/xstate/pull/1202#discussion_r429677773 | ||
useEffect(function () { | ||
@@ -70,0 +74,0 @@ while (effectActionsRef.current.length) { |
@@ -1,20 +0,6 @@ | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
import { useEffect, useRef, useState } from 'react'; | ||
import { useMemo, useRef } from 'react'; | ||
import { useSubscription } from 'use-subscription'; | ||
import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'; | ||
import { isActorWithState } from './useActor'; | ||
import { getServiceSnapshot } from './useService'; | ||
import { getServiceSnapshot } from './utils'; | ||
function isService(actor) { | ||
@@ -34,20 +20,52 @@ return 'state' in actor && 'machine' in actor; | ||
if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; } | ||
var _a = __read(useState(function () { return selector(getSnapshot(actor)); }), 2), selected = _a[0], setSelected = _a[1]; | ||
var selectedRef = useRef(selected); | ||
useEffect(function () { | ||
var updateSelectedIfChanged = function (nextSelected) { | ||
if (!compare(selectedRef.current, nextSelected)) { | ||
setSelected(nextSelected); | ||
selectedRef.current = nextSelected; | ||
var latestSelectorRef = useRef(selector); | ||
var subscription = useMemo(function () { | ||
var snapshot = getSnapshot(actor); | ||
var current = selector(snapshot); | ||
var notifySubscriber; | ||
return { | ||
getSnapshot: function () { return snapshot; }, | ||
getCurrentValue: function () { return current; }, | ||
setCurrentValue: function (newCurrent) { | ||
current = newCurrent; | ||
notifySubscriber === null || notifySubscriber === void 0 ? void 0 : notifySubscriber(); | ||
}, | ||
subscribe: function (callback) { | ||
notifySubscriber = callback; | ||
var sub = actor.subscribe(function (emitted) { | ||
snapshot = emitted; | ||
var next = latestSelectorRef.current(emitted); | ||
if (!compare(current, next)) { | ||
current = next; | ||
callback(); | ||
} | ||
}); | ||
return function () { | ||
sub.unsubscribe(); | ||
}; | ||
} | ||
}; | ||
var initialSelected = selector(getSnapshot(actor)); | ||
updateSelectedIfChanged(initialSelected); | ||
var sub = actor.subscribe(function (emitted) { | ||
var nextSelected = selector(emitted); | ||
updateSelectedIfChanged(nextSelected); | ||
}); | ||
return function () { return sub.unsubscribe(); }; | ||
}, [selector, compare]); | ||
return selected; | ||
// intentionally omit `getSnapshot` and `compare` | ||
// - `getSnapshot`: it is only supposed to read the "initial" snapshot of an actor | ||
// - `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) | ||
}, [actor]); | ||
var currentSelected = useSubscription(subscription); | ||
var currentChanged = false; | ||
if (latestSelectorRef.current !== selector) { | ||
var selected = selector(subscription.getSnapshot()); | ||
if (!compare(currentSelected, selected)) { | ||
currentChanged = true; | ||
currentSelected = selected; | ||
} | ||
} | ||
useIsomorphicLayoutEffect(function () { | ||
latestSelectorRef.current = selector; | ||
// this condition should not be required, but setState bailouts are currently buggy: https://github.com/facebook/react/issues/22654 | ||
if (currentChanged) { | ||
// required so we don't cause a rerender by setting state (this could create infinite rerendering loop with inline selectors) | ||
// 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 | ||
subscription.setCurrentValue(currentSelected); | ||
} | ||
}); | ||
return currentSelected; | ||
} |
@@ -0,2 +1,4 @@ | ||
import { Interpreter } from 'xstate'; | ||
export declare function partition<T, A extends T, B extends T>(items: T[], predicate: (item: T) => item is A): [A[], B[]]; | ||
export declare function getServiceSnapshot<TService extends Interpreter<any, any, any, any>>(service: TService): TService['state']; | ||
//# sourceMappingURL=utils.d.ts.map |
@@ -51,1 +51,4 @@ var __read = (this && this.__read) || function (o, n) { | ||
} | ||
export function getServiceSnapshot(service) { | ||
return service.status !== 0 ? service.state : service.machine.initialState; | ||
} |
@@ -35,3 +35,3 @@ "use strict"; | ||
if (process.env.NODE_ENV !== 'production') { | ||
var _a = __read(react_1.useState(stateMachine), 1), initialMachine = _a[0]; | ||
var _a = __read((0, react_1.useState)(stateMachine), 1), initialMachine = _a[0]; | ||
if (stateMachine !== initialMachine) { | ||
@@ -42,7 +42,7 @@ console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' + | ||
} | ||
var service = useConstant_1.default(function () { | ||
return fsm_1.interpret(fsm_1.createMachine(stateMachine.config, options ? options : stateMachine._options)).start(); | ||
var service = (0, useConstant_1.default)(function () { | ||
return (0, fsm_1.interpret)((0, fsm_1.createMachine)(stateMachine.config, options ? options : stateMachine._options)).start(); | ||
}); | ||
var _b = __read(react_1.useState(function () { return getServiceState(service); }), 2), state = _b[0], setState = _b[1]; | ||
react_1.useEffect(function () { | ||
var _b = __read((0, react_1.useState)(function () { return getServiceState(service); }), 2), state = _b[0], setState = _b[1]; | ||
(0, react_1.useEffect)(function () { | ||
if (options) { | ||
@@ -52,3 +52,3 @@ service._machine._options = options; | ||
}); | ||
react_1.useEffect(function () { | ||
(0, react_1.useEffect)(function () { | ||
service.subscribe(setState); | ||
@@ -63,3 +63,3 @@ return function () { | ||
function useService(service) { | ||
var subscription = react_1.useMemo(function () { | ||
var subscription = (0, react_1.useMemo)(function () { | ||
var currentState = getServiceState(service); | ||
@@ -79,5 +79,5 @@ return { | ||
}, [service]); | ||
var state = use_subscription_1.useSubscription(subscription); | ||
var state = (0, use_subscription_1.useSubscription)(subscription); | ||
return [state, service.send, service]; | ||
} | ||
exports.useService = useService; |
export { useMachine, asEffect, asLayoutEffect } from './useMachine'; | ||
export { useService } from './useService'; | ||
export { useActor } from './useActor'; | ||
@@ -4,0 +3,0 @@ export { useInterpret } from './useInterpret'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.useSpawn = exports.useSelector = exports.useInterpret = exports.useActor = exports.useService = exports.asLayoutEffect = exports.asEffect = exports.useMachine = void 0; | ||
exports.useSpawn = exports.useSelector = exports.useInterpret = exports.useActor = exports.asLayoutEffect = exports.asEffect = exports.useMachine = void 0; | ||
var useMachine_1 = require("./useMachine"); | ||
@@ -8,4 +8,2 @@ Object.defineProperty(exports, "useMachine", { enumerable: true, get: function () { return useMachine_1.useMachine; } }); | ||
Object.defineProperty(exports, "asLayoutEffect", { enumerable: true, get: function () { return useMachine_1.asLayoutEffect; } }); | ||
var useService_1 = require("./useService"); | ||
Object.defineProperty(exports, "useService", { enumerable: true, get: function () { return useService_1.useService; } }); | ||
var useActor_1 = require("./useActor"); | ||
@@ -12,0 +10,0 @@ Object.defineProperty(exports, "useActor", { enumerable: true, get: function () { return useActor_1.useActor; } }); |
import { ActionMeta, ActionObject, EventObject, State, StateConfig } from 'xstate'; | ||
export declare type MaybeLazy<T> = T | (() => T); | ||
export declare type NoInfer<T> = [T][T extends any ? 0 : any]; | ||
export declare type Prop<T, K> = K extends keyof T ? T[K] : never; | ||
export declare enum ReactEffectType { | ||
@@ -5,0 +6,0 @@ Effect = 1, |
@@ -42,6 +42,6 @@ "use strict"; | ||
if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; } | ||
var actorRefRef = react_1.useRef(actorRef); | ||
var deferredEventsRef = react_1.useRef([]); | ||
var _a = __read(react_1.useState(function () { return getSnapshot(actorRef); }), 2), current = _a[0], setCurrent = _a[1]; | ||
var send = useConstant_1.default(function () { return function () { | ||
var actorRefRef = (0, react_1.useRef)(actorRef); | ||
var deferredEventsRef = (0, react_1.useRef)([]); | ||
var _a = __read((0, react_1.useState)(function () { return getSnapshot(actorRef); }), 2), current = _a[0], setCurrent = _a[1]; | ||
var send = (0, useConstant_1.default)(function () { return function () { | ||
var args = []; | ||
@@ -53,3 +53,3 @@ for (var _i = 0; _i < arguments.length; _i++) { | ||
if (process.env.NODE_ENV !== 'production' && args.length > 1) { | ||
console.warn("Unexpected payload: " + JSON.stringify(args[1]) + ". Only a single event object can be sent to actor send() functions."); | ||
console.warn("Unexpected payload: ".concat(JSON.stringify(args[1]), ". Only a single event object can be sent to actor send() functions.")); | ||
} | ||
@@ -67,3 +67,3 @@ var currentActorRef = actorRefRef.current; | ||
}; }); | ||
use_isomorphic_layout_effect_1.default(function () { | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
actorRefRef.current = actorRef; | ||
@@ -70,0 +70,0 @@ setCurrent(getSnapshot(actorRef)); |
@@ -1,16 +0,13 @@ | ||
import { EventObject, StateMachine, State, Interpreter, InterpreterOptions, Typestate, Observer, TypegenConstraint, TypegenDisabled, AreAllImplementationsAssumedToBeProvided, MaybeTypegenMachineOptions, BaseActionObject } from 'xstate'; | ||
import { MaybeLazy, NoInfer } from './types'; | ||
import { AreAllImplementationsAssumedToBeProvided, InternalMachineOptions, InterpreterFrom, InterpreterOptions, Observer, State, StateMachine } from 'xstate'; | ||
import { MaybeLazy } from './types'; | ||
import { UseMachineOptions } from './useMachine'; | ||
export declare function useInterpret<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = { | ||
value: any; | ||
context: TContext; | ||
}, TResolvedTypesMeta extends TypegenConstraint = TypegenDisabled>(...[getMachine, options, observerOrListener]: AreAllImplementationsAssumedToBeProvided<TResolvedTypesMeta> extends false ? [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta, true>, | ||
observerOrListener?: Observer<State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>> | ((value: State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>) => void) | ||
declare type RestParams<TMachine extends StateMachine<any, any, any, any, any, any, any>> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [ | ||
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true>, | ||
observerOrListener?: Observer<State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>> | ((value: State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>) => void) | ||
] : [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options?: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta>, | ||
observerOrListener?: Observer<State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>> | ((value: State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>) => void) | ||
]): Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta>; | ||
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']>, | ||
observerOrListener?: Observer<State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>> | ((value: State<TMachine['__TContext'], TMachine['__TEvent'], any, TMachine['__TTypestate'], TMachine['__TResolvedTypesMeta']>) => void) | ||
]; | ||
export declare function useInterpret<TMachine extends StateMachine<any, any, any, any, any, any, any>>(getMachine: MaybeLazy<TMachine>, ...[options, observerOrListener]: RestParams<TMachine>): InterpreterFrom<TMachine>; | ||
export {}; | ||
//# sourceMappingURL=useInterpret.d.ts.map |
@@ -60,9 +60,9 @@ "use strict"; | ||
} | ||
function useInterpret() { | ||
function useInterpret(getMachine) { | ||
var _a = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
_a[_i] = arguments[_i]; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
_a[_i - 1] = arguments[_i]; | ||
} | ||
var _b = __read(_a, 3), getMachine = _b[0], _c = _b[1], options = _c === void 0 ? {} : _c, observerOrListener = _b[2]; | ||
var machine = useConstant_1.default(function () { | ||
var _b = __read(_a, 2), _c = _b[0], options = _c === void 0 ? {} : _c, observerOrListener = _b[1]; | ||
var machine = (0, useConstant_1.default)(function () { | ||
return typeof getMachine === 'function' ? getMachine() : getMachine; | ||
@@ -72,4 +72,4 @@ }); | ||
typeof getMachine !== 'function') { | ||
var _d = __read(react_1.useState(machine), 1), initialMachine = _d[0]; | ||
if (machine !== initialMachine) { | ||
var _d = __read((0, react_1.useState)(machine), 1), initialMachine = _d[0]; | ||
if (getMachine !== initialMachine) { | ||
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' + | ||
@@ -82,3 +82,3 @@ 'Please make sure that you pass the same Machine as argument each time.'); | ||
var activities = options.activities; | ||
var service = useConstant_1.default(function () { | ||
var service = (0, useConstant_1.default)(function () { | ||
var machineConfig = { | ||
@@ -93,5 +93,5 @@ context: context, | ||
var machineWithConfig = machine.withConfig(machineConfig, function () { return (__assign(__assign({}, machine.context), context)); }); | ||
return xstate_1.interpret(machineWithConfig, __assign({ deferEvents: true }, interpreterOptions)); | ||
return (0, xstate_1.interpret)(machineWithConfig, __assign({ deferEvents: true }, interpreterOptions)); | ||
}); | ||
use_isomorphic_layout_effect_1.default(function () { | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
var sub; | ||
@@ -105,3 +105,3 @@ if (observerOrListener) { | ||
}, [observerOrListener]); | ||
use_isomorphic_layout_effect_1.default(function () { | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
service.start(rehydratedState ? xstate_1.State.create(rehydratedState) : undefined); | ||
@@ -115,3 +115,3 @@ return function () { | ||
// in one place -- this hook's caller. | ||
use_isomorphic_layout_effect_1.default(function () { | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
Object.assign(service.machine.options.actions, actions); | ||
@@ -123,5 +123,5 @@ Object.assign(service.machine.options.guards, guards); | ||
}, [actions, guards, activities, services, delays]); | ||
useReactEffectActions_1.useReactEffectActions(service); | ||
(0, useReactEffectActions_1.useReactEffectActions)(service); | ||
return service; | ||
} | ||
exports.useInterpret = useInterpret; |
@@ -1,3 +0,3 @@ | ||
import { ActionFunction, AreAllImplementationsAssumedToBeProvided, BaseActionObject, EventObject, Interpreter, InterpreterOptions, MaybeTypegenMachineOptions, State, StateConfig, StateMachine, TypegenConstraint, TypegenDisabled, Typestate } from 'xstate'; | ||
import { MaybeLazy, NoInfer, ReactActionFunction } from './types'; | ||
import { ActionFunction, AreAllImplementationsAssumedToBeProvided, EventObject, InternalMachineOptions, InterpreterFrom, InterpreterOptions, StateConfig, StateFrom, StateMachine } from 'xstate'; | ||
import { MaybeLazy, Prop, ReactActionFunction } from './types'; | ||
export declare function asEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>; | ||
@@ -16,16 +16,10 @@ export declare function asLayoutEffect<TContext, TEvent extends EventObject>(exec: ActionFunction<TContext, TEvent>): ReactActionFunction<TContext, TEvent>; | ||
} | ||
export declare function useMachine<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = { | ||
value: any; | ||
context: TContext; | ||
}, TResolvedTypesMeta extends TypegenConstraint = TypegenDisabled>(...[getMachine, options]: AreAllImplementationsAssumedToBeProvided<TResolvedTypesMeta> extends false ? [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta, true> | ||
declare type RestParams<TMachine extends StateMachine<any, any, any, any, any, any, any>> = AreAllImplementationsAssumedToBeProvided<TMachine['__TResolvedTypesMeta']> extends false ? [ | ||
options: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta'], true> | ||
] : [ | ||
getMachine: MaybeLazy<StateMachine<TContext, any, TEvent, TTypestate, any, TResolvedTypesMeta>>, | ||
options?: InterpreterOptions & UseMachineOptions<TContext, TEvent> & MaybeTypegenMachineOptions<TContext, NoInfer<TEvent>, BaseActionObject, TResolvedTypesMeta> | ||
]): [ | ||
State<TContext, TEvent, any, TTypestate, TResolvedTypesMeta>, | ||
Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta>['send'], | ||
Interpreter<TContext, any, TEvent, TTypestate, TResolvedTypesMeta> | ||
options?: InterpreterOptions & UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> & InternalMachineOptions<TMachine['__TContext'], TMachine['__TEvent'], TMachine['__TResolvedTypesMeta']> | ||
]; | ||
declare type UseMachineReturn<TMachine extends StateMachine<any, any, any, any, any, any, any>, TInterpreter = InterpreterFrom<TMachine>> = [StateFrom<TMachine>, Prop<TInterpreter, 'send'>, TInterpreter]; | ||
export declare function useMachine<TMachine extends StateMachine<any, any, any, any, any, any, any>>(getMachine: MaybeLazy<TMachine>, ...[options]: RestParams<TMachine>): UseMachineReturn<TMachine>; | ||
export {}; | ||
//# sourceMappingURL=useMachine.d.ts.map |
@@ -18,6 +18,10 @@ "use strict"; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -38,7 +42,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
return function () { | ||
return exec.apply(void 0, __spreadArray([], __read(args))); | ||
return exec.apply(void 0, __spreadArray([], __read(args), false)); | ||
}; | ||
}; | ||
Object.defineProperties(effectExec, { | ||
name: { value: "effect:" + exec.name }, | ||
name: { value: "effect:".concat(exec.name) }, | ||
__effect: { value: tag } | ||
@@ -56,9 +60,9 @@ }); | ||
exports.asLayoutEffect = asLayoutEffect; | ||
function useMachine() { | ||
function useMachine(getMachine) { | ||
var _a = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
_a[_i] = arguments[_i]; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
_a[_i - 1] = arguments[_i]; | ||
} | ||
var _b = __read(_a, 2), getMachine = _b[0], _c = _b[1], options = _c === void 0 ? {} : _c; | ||
var listener = react_1.useCallback(function (nextState) { | ||
var _b = __read(_a, 1), _c = _b[0], options = _c === void 0 ? {} : _c; | ||
var listener = (0, react_1.useCallback)(function (nextState) { | ||
// Only change the current state if: | ||
@@ -69,4 +73,3 @@ // - the incoming state is the "live" initial state (since it might have new actors) | ||
// The "live" initial state will have .changed === undefined. | ||
var initialStateChanged = nextState.changed === undefined && | ||
Object.keys(nextState.children).length; | ||
var initialStateChanged = nextState.changed === undefined && Object.keys(nextState.children).length; | ||
if (nextState.changed || initialStateChanged) { | ||
@@ -76,4 +79,4 @@ setState(nextState); | ||
}, []); | ||
var service = useInterpret_1.useInterpret(getMachine, options, listener); | ||
var _d = __read(react_1.useState(function () { | ||
var service = (0, useInterpret_1.useInterpret)(getMachine, options, listener); | ||
var _d = __read((0, react_1.useState)(function () { | ||
var initialState = service.machine.initialState; | ||
@@ -80,0 +83,0 @@ return (options.state |
@@ -18,6 +18,10 @@ "use strict"; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -40,5 +44,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
function useReactEffectActions(service) { | ||
var effectActionsRef = react_1.useRef([]); | ||
var layoutEffectActionsRef = react_1.useRef([]); | ||
use_isomorphic_layout_effect_1.default(function () { | ||
var effectActionsRef = (0, react_1.useRef)([]); | ||
var layoutEffectActionsRef = (0, react_1.useRef)([]); | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
var sub = service.subscribe(function (currentState) { | ||
@@ -51,7 +55,7 @@ var _a, _b; | ||
}); | ||
var _c = __read(utils_1.partition(reactEffectActions, function (action) { | ||
var _c = __read((0, utils_1.partition)(reactEffectActions, function (action) { | ||
return action.exec.__effect === types_1.ReactEffectType.Effect; | ||
}), 2), effectActions = _c[0], layoutEffectActions = _c[1]; | ||
(_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })))); | ||
(_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })))); | ||
(_a = effectActionsRef.current).push.apply(_a, __spreadArray([], __read(effectActions.map(function (effectAction) { return [effectAction, currentState]; })), false)); | ||
(_b = layoutEffectActionsRef.current).push.apply(_b, __spreadArray([], __read(layoutEffectActions.map(function (layoutEffectAction) { return [layoutEffectAction, currentState]; })), false)); | ||
} | ||
@@ -66,3 +70,3 @@ }); | ||
// so we have to use `useIsomorphicLayoutEffect` to silence those warnings | ||
use_isomorphic_layout_effect_1.default(function () { | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
while (layoutEffectActionsRef.current.length) { | ||
@@ -72,4 +76,4 @@ var _a = __read(layoutEffectActionsRef.current.shift(), 2), layoutEffectAction = _a[0], effectState = _a[1]; | ||
} | ||
}); // https://github.com/davidkpiano/xstate/pull/1202#discussion_r429677773 | ||
react_1.useEffect(function () { | ||
}); // https://github.com/statelyai/xstate/pull/1202#discussion_r429677773 | ||
(0, react_1.useEffect)(function () { | ||
while (effectActionsRef.current.length) { | ||
@@ -76,0 +80,0 @@ var _a = __read(effectActionsRef.current.shift(), 2), effectAction = _a[0], effectState = _a[1]; |
"use strict"; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.useSelector = void 0; | ||
var react_1 = require("react"); | ||
var use_subscription_1 = require("use-subscription"); | ||
var use_isomorphic_layout_effect_1 = require("use-isomorphic-layout-effect"); | ||
var useActor_1 = require("./useActor"); | ||
var useService_1 = require("./useService"); | ||
var utils_1 = require("./utils"); | ||
function isService(actor) { | ||
@@ -29,4 +15,4 @@ return 'state' in actor && 'machine' in actor; | ||
return isService(a) | ||
? useService_1.getServiceSnapshot(a) | ||
: useActor_1.isActorWithState(a) | ||
? (0, utils_1.getServiceSnapshot)(a) | ||
: (0, useActor_1.isActorWithState)(a) | ||
? a.state | ||
@@ -38,21 +24,53 @@ : undefined; | ||
if (getSnapshot === void 0) { getSnapshot = defaultGetSnapshot; } | ||
var _a = __read(react_1.useState(function () { return selector(getSnapshot(actor)); }), 2), selected = _a[0], setSelected = _a[1]; | ||
var selectedRef = react_1.useRef(selected); | ||
react_1.useEffect(function () { | ||
var updateSelectedIfChanged = function (nextSelected) { | ||
if (!compare(selectedRef.current, nextSelected)) { | ||
setSelected(nextSelected); | ||
selectedRef.current = nextSelected; | ||
var latestSelectorRef = (0, react_1.useRef)(selector); | ||
var subscription = (0, react_1.useMemo)(function () { | ||
var snapshot = getSnapshot(actor); | ||
var current = selector(snapshot); | ||
var notifySubscriber; | ||
return { | ||
getSnapshot: function () { return snapshot; }, | ||
getCurrentValue: function () { return current; }, | ||
setCurrentValue: function (newCurrent) { | ||
current = newCurrent; | ||
notifySubscriber === null || notifySubscriber === void 0 ? void 0 : notifySubscriber(); | ||
}, | ||
subscribe: function (callback) { | ||
notifySubscriber = callback; | ||
var sub = actor.subscribe(function (emitted) { | ||
snapshot = emitted; | ||
var next = latestSelectorRef.current(emitted); | ||
if (!compare(current, next)) { | ||
current = next; | ||
callback(); | ||
} | ||
}); | ||
return function () { | ||
sub.unsubscribe(); | ||
}; | ||
} | ||
}; | ||
var initialSelected = selector(getSnapshot(actor)); | ||
updateSelectedIfChanged(initialSelected); | ||
var sub = actor.subscribe(function (emitted) { | ||
var nextSelected = selector(emitted); | ||
updateSelectedIfChanged(nextSelected); | ||
}); | ||
return function () { return sub.unsubscribe(); }; | ||
}, [selector, compare]); | ||
return selected; | ||
// intentionally omit `getSnapshot` and `compare` | ||
// - `getSnapshot`: it is only supposed to read the "initial" snapshot of an actor | ||
// - `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) | ||
}, [actor]); | ||
var currentSelected = (0, use_subscription_1.useSubscription)(subscription); | ||
var currentChanged = false; | ||
if (latestSelectorRef.current !== selector) { | ||
var selected = selector(subscription.getSnapshot()); | ||
if (!compare(currentSelected, selected)) { | ||
currentChanged = true; | ||
currentSelected = selected; | ||
} | ||
} | ||
(0, use_isomorphic_layout_effect_1.default)(function () { | ||
latestSelectorRef.current = selector; | ||
// this condition should not be required, but setState bailouts are currently buggy: https://github.com/facebook/react/issues/22654 | ||
if (currentChanged) { | ||
// required so we don't cause a rerender by setting state (this could create infinite rerendering loop with inline selectors) | ||
// 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 | ||
subscription.setCurrentValue(currentSelected); | ||
} | ||
}); | ||
return currentSelected; | ||
} | ||
exports.useSelector = useSelector; |
@@ -14,4 +14,4 @@ "use strict"; | ||
function useSpawn(behavior) { | ||
var actorRef = useConstant_1.default(function () { | ||
return behaviors_1.spawnBehavior(behavior); | ||
var actorRef = (0, useConstant_1.default)(function () { | ||
return (0, behaviors_1.spawnBehavior)(behavior); | ||
}); | ||
@@ -18,0 +18,0 @@ return actorRef; |
@@ -0,2 +1,4 @@ | ||
import { Interpreter } from 'xstate'; | ||
export declare function partition<T, A extends T, B extends T>(items: T[], predicate: (item: T) => item is A): [A[], B[]]; | ||
export declare function getServiceSnapshot<TService extends Interpreter<any, any, any, any>>(service: TService): TService['state']; | ||
//# sourceMappingURL=utils.d.ts.map |
@@ -30,3 +30,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.partition = void 0; | ||
exports.getServiceSnapshot = exports.partition = void 0; | ||
function partition(items, predicate) { | ||
@@ -56,1 +56,5 @@ var e_1, _a; | ||
exports.partition = partition; | ||
function getServiceSnapshot(service) { | ||
return service.status !== 0 ? service.state : service.machine.initialState; | ||
} | ||
exports.getServiceSnapshot = getServiceSnapshot; |
{ | ||
"name": "@xstate/react", | ||
"version": "2.0.0-pr2674-20219612435", | ||
"version": "2.0.0", | ||
"description": "XState tools for React", | ||
@@ -16,3 +16,3 @@ "keywords": [ | ||
"author": "David Khourshid <davidkpiano@gmail.com>", | ||
"homepage": "https://github.com/davidkpiano/xstate/tree/main/packages/xstate-react#readme", | ||
"homepage": "https://github.com/statelyai/xstate/tree/main/packages/xstate-react#readme", | ||
"license": "MIT", | ||
@@ -44,3 +44,3 @@ "main": "lib/index.js", | ||
"type": "git", | ||
"url": "git+ssh://git@github.com/davidkpiano/xstate.git" | ||
"url": "git+ssh://git@github.com/statelyai/xstate.git" | ||
}, | ||
@@ -51,11 +51,11 @@ "scripts": { | ||
"test": "jest", | ||
"prepublish": "npm run build && npm run test" | ||
"prepare": "npm run build" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/davidkpiano/xstate/issues" | ||
"url": "https://github.com/statelyai/xstate/issues" | ||
}, | ||
"peerDependencies": { | ||
"@xstate/fsm": "^1.0.0", | ||
"@xstate/fsm": "^1.6.4", | ||
"react": "^16.8.0 || ^17.0.0", | ||
"xstate": "^4.26.0-pr2674-20219612435" | ||
"xstate": "^4.29.0" | ||
}, | ||
@@ -93,5 +93,5 @@ "peerDependenciesMeta": { | ||
"ts-jest": "^26.5.6", | ||
"typescript": "^4.3.5", | ||
"typescript": "^4.5.2", | ||
"xstate": "*" | ||
} | ||
} |
517
README.md
# @xstate/react | ||
[[toc]] | ||
This package contains utilities for using [XState](https://github.com/statelyai/xstate) with [React](https://github.com/facebook/react/). | ||
## Quick Start | ||
- [Read the full documentation in the XState docs](https://xstate.js.org/docs/packages/xstate-react/). | ||
- [Read our contribution guidelines](https://github.com/statelyai/xstate/blob/main/CONTRIBUTING.md). | ||
## Quick start | ||
1. Install `xstate` and `@xstate/react`: | ||
@@ -60,511 +63,1 @@ | ||
``` | ||
## Examples | ||
- [XState + React TodoMVC (CodeSandbox)](https://codesandbox.io/s/xstate-todomvc-33wr94qv1) | ||
## API | ||
### `useMachine(machine, options?)` | ||
A [React hook](https://reactjs.org/hooks) that interprets the given `machine` and starts a service that runs for the lifetime of the component. | ||
**Arguments** | ||
- `machine` - An [XState machine](https://xstate.js.org/docs/guides/machines.html) or a function that lazily returns a machine: | ||
```js | ||
// existing machine | ||
const [state, send] = useMachine(machine); | ||
// lazily-created machine | ||
const [state, send] = useMachine(() => | ||
createMachine({ | ||
/* ... */ | ||
}) | ||
); | ||
``` | ||
- `options` (optional) - [Interpreter options](https://xstate.js.org/docs/guides/interpretation.html#options) and/or any of the following machine config options: `guards`, `actions`, `services`, `delays`, `immediate`, `context`, `state`. | ||
**Returns** a tuple of `[state, send, service]`: | ||
- `state` - Represents the current state of the machine as an XState `State` object. | ||
- `send` - A function that sends events to the running service. | ||
- `service` - The created service. | ||
### `useService(service)` | ||
::: warning Deprecated | ||
In the next major version, `useService(service)` will be replaced with `useActor(service)`. Prefer using the `useActor(service)` hook for services instead, since services are also actors. | ||
Also, keep in mind that only a single argument (the event object) can be sent to `send(eventObject)` from `useActor(...)`. When migrating to `useActor(...)`, refactor `send(...)` calls to use only a single event object: | ||
```diff | ||
const [state, send] = useActor(service); | ||
-send('CLICK', { x: 0, y: 3 }); | ||
+send({ type: 'CLICK', x: 0, y: 3 }); | ||
``` | ||
::: | ||
A [React hook](https://reactjs.org/hooks) that subscribes to state changes from an existing [service](https://xstate.js.org/docs/guides/interpretation.html). | ||
**Arguments** | ||
- `service` - An [XState service](https://xstate.js.org/docs/guides/interpretation.html). | ||
**Returns** a tuple of `[state, send]`: | ||
- `state` - Represents the current state of the service as an XState `State` object. | ||
- `send` - A function that sends events to the running service. | ||
### `useActor(actor, getSnapshot?)` | ||
A [React hook](https://reactjs.org/hooks) that subscribes to emitted changes from an existing [actor](https://xstate.js.org/docs/guides/actors.html). | ||
**Arguments** | ||
- `actor` - an actor-like object that contains `.send(...)` and `.subscribe(...)` methods. | ||
- `getSnapshot` - a function that should return the latest emitted value from the `actor`. | ||
- Defaults to attempting to get the `actor.state`, or returning `undefined` if that does not exist. | ||
```js | ||
const [state, send] = useActor(someSpawnedActor); | ||
// with custom actors | ||
const [state, send] = useActor(customActor, (actor) => { | ||
// implementation-specific pseudocode example: | ||
return actor.getLastEmittedValue(); | ||
}); | ||
``` | ||
### `useInterpret(machine, options?, observer?)` | ||
A React hook that returns the `service` created from the `machine` with the `options`, if specified. It also sets up a subscription to the `service` with the `observer`, if provided. | ||
_Since 1.3.0_ | ||
**Arguments** | ||
- `machine` - An [XState machine](https://xstate.js.org/docs/guides/machines.html) or a function that lazily returns a machine. | ||
- `options` (optional) - [Interpreter options](https://xstate.js.org/docs/guides/interpretation.html#options) and/or any of the following machine config options: `guards`, `actions`, `services`, `delays`, `immediate`, `context`, `state`. | ||
- `observer` (optional) - an observer or listener that listens to state updates: | ||
- an observer (e.g., `{ next: (state) => {/* ... */} }`) | ||
- or a listener (e.g., `(state) => {/* ... */}`) | ||
```js | ||
import { useInterpret } from '@xstate/react'; | ||
import { someMachine } from '../path/to/someMachine'; | ||
const App = () => { | ||
const service = useInterpret(someMachine); | ||
// ... | ||
}; | ||
``` | ||
With options + listener: | ||
```js | ||
// ... | ||
const App = () => { | ||
const service = useInterpret( | ||
someMachine, | ||
{ | ||
actions: { | ||
/* ... */ | ||
} | ||
}, | ||
(state) => { | ||
// subscribes to state changes | ||
console.log(state); | ||
} | ||
); | ||
// ... | ||
}; | ||
``` | ||
### `useSelector(actor, selector, compare?, getSnapshot?)` | ||
A React hook that returns the selected value from the snapshot of an `actor`, such as a service. This hook will only cause a rerender if the selected value changes, as determined by the optional `compare` function. | ||
_Since 1.3.0_ | ||
**Arguments** | ||
- `actor` - a service or an actor-like object that contains `.send(...)` and `.subscribe(...)` methods. | ||
- `selector` - a function that takes in an actor's "current state" (snapshot) as an argument and returns the desired selected value. | ||
- `compare` (optional) - a function that determines if the current selected value is the same as the previous selected value. | ||
- `getSnapshot` (optional) - a function that should return the latest emitted value from the `actor`. | ||
- Defaults to attempting to get the `actor.state`, or returning `undefined` if that does not exist. Will automatically pull the state from services. | ||
```js | ||
import { useSelector } from '@xstate/react'; | ||
// tip: optimize selectors by defining them externally when possible | ||
const selectCount = (state) => state.context.count; | ||
const App = ({ service }) => { | ||
const count = useSelector(service, selectCount); | ||
// ... | ||
}; | ||
``` | ||
With `compare` function: | ||
```js | ||
// ... | ||
const selectUser = (state) => state.context.user; | ||
const compareUser = (prevUser, nextUser) => prevUser.id === nextUser.id; | ||
const App = ({ service }) => { | ||
const user = useSelector(service, selectUser, compareUser); | ||
// ... | ||
}; | ||
``` | ||
With `useInterpret(...)`: | ||
```js | ||
import { useInterpret, useSelector } from '@xstate/react'; | ||
import { someMachine } from '../path/to/someMachine'; | ||
const selectCount = (state) => state.context.count; | ||
const App = ({ service }) => { | ||
const service = useInterpret(someMachine); | ||
const count = useSelector(service, selectCount); | ||
// ... | ||
}; | ||
``` | ||
### `asEffect(action)` | ||
Ensures that the `action` is executed as an effect in `useEffect`, rather than being immediately executed. | ||
**Arguments** | ||
- `action` - An action function (e.g., `(context, event) => { alert(context.message) })`) | ||
**Returns** a special action function that wraps the original so that `useMachine` knows to execute it in `useEffect`. | ||
**Example** | ||
```jsx | ||
const machine = createMachine({ | ||
initial: 'focused', | ||
states: { | ||
focused: { | ||
entry: 'focus' | ||
} | ||
} | ||
}); | ||
const Input = () => { | ||
const inputRef = useRef(null); | ||
const [state, send] = useMachine(machine, { | ||
actions: { | ||
focus: asEffect((context, event) => { | ||
inputRef.current && inputRef.current.focus(); | ||
}) | ||
} | ||
}); | ||
return <input ref={inputRef} />; | ||
}; | ||
``` | ||
### `asLayoutEffect(action)` | ||
Ensures that the `action` is executed as an effect in `useLayoutEffect`, rather than being immediately executed. | ||
**Arguments** | ||
- `action` - An action function (e.g., `(context, event) => { alert(context.message) })`) | ||
**Returns** a special action function that wraps the original so that `useMachine` knows to execute it in `useLayoutEffect`. | ||
### `useMachine(machine)` with `@xstate/fsm` | ||
A [React hook](https://reactjs.org/hooks) that interprets the given finite state `machine` from [`@xstate/fsm`] and starts a service that runs for the lifetime of the component. | ||
This special `useMachine` hook is imported from `@xstate/react/fsm` | ||
**Arguments** | ||
- `machine` - An [XState finite state machine (FSM)](https://xstate.js.org/docs/packages/xstate-fsm/). | ||
- `options` - An optional `options` object. | ||
**Returns** a tuple of `[state, send, service]`: | ||
- `state` - Represents the current state of the machine as an `@xstate/fsm` `StateMachine.State` object. | ||
- `send` - A function that sends events to the running service. | ||
- `service` - The created `@xstate/fsm` service. | ||
**Example** | ||
```js | ||
import { useEffect } from 'react'; | ||
import { useMachine } from '@xstate/react/fsm'; | ||
import { createMachine } from '@xstate/fsm'; | ||
const context = { | ||
data: undefined | ||
}; | ||
const fetchMachine = createMachine({ | ||
id: 'fetch', | ||
initial: 'idle', | ||
context, | ||
states: { | ||
idle: { | ||
on: { FETCH: 'loading' } | ||
}, | ||
loading: { | ||
entry: ['load'], | ||
on: { | ||
RESOLVE: { | ||
target: 'success', | ||
actions: assign({ | ||
data: (context, event) => event.data | ||
}) | ||
} | ||
} | ||
}, | ||
success: {} | ||
} | ||
}); | ||
const Fetcher = ({ | ||
onFetch = () => new Promise((res) => res('some data')) | ||
}) => { | ||
const [state, send] = useMachine(fetchMachine, { | ||
actions: { | ||
load: () => { | ||
onFetch().then((res) => { | ||
send({ type: 'RESOLVE', data: res }); | ||
}); | ||
} | ||
} | ||
}); | ||
switch (state.value) { | ||
case 'idle': | ||
return <button onClick={(_) => send('FETCH')}>Fetch</button>; | ||
case 'loading': | ||
return <div>Loading...</div>; | ||
case 'success': | ||
return ( | ||
<div> | ||
Success! Data: <div data-testid="data">{state.context.data}</div> | ||
</div> | ||
); | ||
default: | ||
return null; | ||
} | ||
}; | ||
``` | ||
## Configuring Machines | ||
Existing machines can be configured by passing the machine options as the 2nd argument of `useMachine(machine, options)`. | ||
Example: the `'fetchData'` service and `'notifySuccess'` action are both configurable: | ||
```js | ||
const fetchMachine = createMachine({ | ||
id: 'fetch', | ||
initial: 'idle', | ||
context: { | ||
data: undefined, | ||
error: undefined | ||
}, | ||
states: { | ||
idle: { | ||
on: { FETCH: 'loading' } | ||
}, | ||
loading: { | ||
invoke: { | ||
src: 'fetchData', | ||
onDone: { | ||
target: 'success', | ||
actions: assign({ | ||
data: (_, event) => event.data | ||
}) | ||
}, | ||
onError: { | ||
target: 'failure', | ||
actions: assign({ | ||
error: (_, event) => event.data | ||
}) | ||
} | ||
} | ||
}, | ||
success: { | ||
entry: 'notifySuccess', | ||
type: 'final' | ||
}, | ||
failure: { | ||
on: { | ||
RETRY: 'loading' | ||
} | ||
} | ||
} | ||
}); | ||
const Fetcher = ({ onResolve }) => { | ||
const [state, send] = useMachine(fetchMachine, { | ||
actions: { | ||
notifySuccess: (ctx) => onResolve(ctx.data) | ||
}, | ||
services: { | ||
fetchData: (_, e) => | ||
fetch(`some/api/${e.query}`).then((res) => res.json()) | ||
} | ||
}); | ||
switch (state.value) { | ||
case 'idle': | ||
return ( | ||
<button onClick={() => send('FETCH', { query: 'something' })}> | ||
Search for something | ||
</button> | ||
); | ||
case 'loading': | ||
return <div>Searching...</div>; | ||
case 'success': | ||
return <div>Success! Data: {state.context.data}</div>; | ||
case 'failure': | ||
return ( | ||
<> | ||
<p>{state.context.error.message}</p> | ||
<button onClick={() => send('RETRY')}>Retry</button> | ||
</> | ||
); | ||
default: | ||
return null; | ||
} | ||
}; | ||
``` | ||
## Matching States | ||
When using [hierarchical](https://xstate.js.org/docs/guides/hierarchical.html) and [parallel](https://xstate.js.org/docs/guides/parallel.html) machines, the state values will be objects, not strings. In this case, it is best to use [`state.matches(...)`](https://xstate.js.org/docs/guides/states.html#state-methods-and-getters). | ||
We can do this with `if/else if/else` blocks: | ||
```js | ||
// ... | ||
if (state.matches('idle')) { | ||
return /* ... */; | ||
} else if (state.matches({ loading: 'user' })) { | ||
return /* ... */; | ||
} else if (state.matches({ loading: 'friends' })) { | ||
return /* ... */; | ||
} else { | ||
return null; | ||
} | ||
``` | ||
We can also continue to use `switch`, but we must make an adjustment to our approach. By setting the expression of the `switch` to `true`, we can use [`state.matches(...)`](https://xstate.js.org/docs/guides/states.html#state-methods-and-getters) as a predicate in each `case`: | ||
```js | ||
switch (true) { | ||
case state.matches('idle'): | ||
return /* ... */; | ||
case state.matches({ loading: 'user' }): | ||
return /* ... */; | ||
case state.matches({ loading: 'friends' }): | ||
return /* ... */; | ||
default: | ||
return null; | ||
} | ||
``` | ||
A ternary statement can also be considered, especially within rendered JSX: | ||
```jsx | ||
const Loader = () => { | ||
const [state, send] = useMachine(/* ... */); | ||
return ( | ||
<div> | ||
{state.matches('idle') ? ( | ||
<Loader.Idle /> | ||
) : state.matches({ loading: 'user' }) ? ( | ||
<Loader.LoadingUser /> | ||
) : state.matches({ loading: 'friends' }) ? ( | ||
<Loader.LoadingFriends /> | ||
) : null} | ||
</div> | ||
); | ||
}; | ||
``` | ||
## Persisted and Rehydrated State | ||
You can persist and rehydrate state with `useMachine(...)` via `options.state`: | ||
```js | ||
// ... | ||
// Get the persisted state config object from somewhere, e.g. localStorage | ||
const persistedState = JSON.parse(localStorage.getItem('some-persisted-state-key')) || someMachine.initialState; | ||
const App = () => { | ||
const [state, send] = useMachine(someMachine, { | ||
state: persistedState // provide persisted state config object here | ||
}); | ||
// state will initially be that persisted state, not the machine's initialState | ||
return (/* ... */) | ||
} | ||
``` | ||
## Services | ||
The `service` created in `useMachine(machine)` can be referenced as the third returned value: | ||
```js | ||
// vvvvvvv | ||
const [state, send, service] = useMachine(someMachine); | ||
``` | ||
You can subscribe to that service's state changes with the [`useEffect` hook](https://reactjs.org/docs/hooks-effect.html): | ||
```js | ||
// ... | ||
useEffect(() => { | ||
const subscription = service.subscribe((state) => { | ||
// simple state logging | ||
console.log(state); | ||
}); | ||
return subscription.unsubscribe; | ||
}, [service]); // note: service should never change | ||
``` | ||
## Migration from 0.x | ||
- For spawned actors created using `invoke` or `spawn(...)`, use the `useActor()` hook instead of `useService()`: | ||
```diff | ||
-import { useService } from '@xstate/react'; | ||
+import { useActor } from '@xstate/react'; | ||
-const [state, send] = useService(someActor); | ||
+const [state, send] = useActor(someActor); | ||
``` | ||
## Resources | ||
[State Machines in React](https://gedd.ski/post/state-machines-in-react/) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
2
6
102886
51
1531
63