Changelog
4.0.0-beta.11
Minor Changes
4.0.0-beta.10
Minor Changes
- #4240
409552cf8
Thanks @davidkpiano! - TheuseMachine
function is aliased touseActor
and not shown as visually deprecated.
4.0.0-beta.9
Major Changes
- #4265
1153b3f9a
Thanks @davidkpiano! - FSM-related functions have been removed.
4.0.0-beta.8
Patch Changes
4.0.0-beta.7
Major Changes
-
#4050
fc88dc8e6
Thanks @davidkpiano! - Theoptions
prop has been added (back) to theContext.Provider
component returned fromcreateActorContext
:const SomeContext = createActorContext(someMachine); // ... <SomeContext.Provider options={{ input: 42 }}> {/* ... */} </SomeContext.Provider>;
Minor Changes
- #4050
fc88dc8e6
Thanks @davidkpiano! - TheobserverOrListener
argument has been removed from the 3rd argument ofcreateActorContext(logic, options)
.
4.0.0-beta.6
Major Changes
- #4041
50fe8cdd4
Thanks @davidkpiano! - Instances of "behavior" in the codebase have been replaced with "actor logic".
4.0.0-beta.5
Patch Changes
- #4033
9cb7cb51a
Thanks @Andarist! - Fixed generated TS declaration files to not include.ts
extensions in the import/export statements.
4.0.0-beta.4
Major Changes
-
#3947
5fa3a0c74
Thanks @davidkpiano! - Removed the ability to pass a factory function as argument touseMachine
anduseInterpret
. -
#4006
42df9a536
Thanks @davidkpiano! -useActorRef
is introduced, which returns anActorRef
from actor logic:const actorRef = useActorRef(machine, { ... }); const anotherActorRef = useActorRef(fromPromise(...));
is deprecated in favor ofuseMachine
useActor
, which works with machines and any other kind of logic-const [state, send] = useMachine(machine); +const [state, send] = useActor(machine); const [state, send] = useActor(fromTransition(...));
is removed in favor ofuseSpawn
useActorRef
-const actorRef = useSpawn(machine); +const actorRef = useActorRef(machine); The previous use of `useActor(actorRef)` is now replaced with just using the `actorRef` directly, and with `useSelector`: ```diff -const [state, send] = useActor(actorRef); +const state = useSelector(actorRef, s => s); // actorRef.send(...)
-
#4006
42df9a536
Thanks @davidkpiano! -useActor
has been removed from the created actor context, you should be able to replace its usage withMyCtx.useSelector
andMyCtx.useActorRef
. -
#3947
5fa3a0c74
Thanks @davidkpiano! - Implementations for machines onuseMachine
anduseInterpret
hooks should go directly on the machine viamachine.provide(...)
, and are no longer allowed to be passed in as options.-const [state, send] = useMachine(machine, { - actions: { - // ... - } -}); +const [state, send] = useMachine(machine.provide({ + actions: { + // ... + } +}));
@xstate/react
will detect that the machine's config is still the same, and will not produce the "machine has changed" warning.
3.2.2
Patch Changes
- #3919
6665f0a32
Thanks @c-w! - Updated the allowed range for theuse-isomorphic-layout-effect
dependency.
4.0.0-beta.3
4.0.0-alpha.2
Patch Changes
- #3944
305a89001
Thanks @Andarist! - Releasing adjusted internals to make the alpha version of this module compatible with the current version ofxstate@alpha
3.2.1
Patch Changes
- #3829
c110c429d
Thanks @Andarist! - Fixed compatibility of the generated TS types forcreateActorContext
with pre-4.7.
3.2.0
Minor Changes
-
#3814
494203b3d
Thanks @Andarist! - TheProvider
fromcreateActorContext(...)
now accepts theoptions={{...}}
prop that takes the same object as the second argument to theuseMachine(machine, options)
hook.These options are no longer passed as the second argument to the
createActorContext(machine)
function:-const SomeContext = createActorContext(someMachine, - { actions: { ... } }); +const SomeContext = createActorContext(someMachine); // ... -<SomeContext.Provider> +<SomeContext.Provider options={{ actions: { ... } }}> // ...
3.1.2
Patch Changes
- #3804
b53856d28
Thanks @farskid! - Interpreter options can now be specified in the second argument of createActorContext(machine, options).
3.1.1
Patch Changes
- #3799
51d254692
Thanks @Andarist! - Fixed an issue that caused the internally useduseSyncExternalStore
to warn about the computed snapshot not being cached when a not-started machine service was passed touseActor
.
3.1.0
Minor Changes
-
#3778
f12248b23
Thanks @davidkpiano! - ThecreateActorContext(...)
helper has been introduced to make global actors easier to use with React. It outputs a React Context object with the following properties:.Provider
- The React Context provider.useActor(...)
- A hook that can be used to get the current state and send events to the actor.useSelector(...)
- A hook that can be used to select some derived state from the actor's state.useActorRef()
- A hook that can be used to get a reference to the actor that can be passed to other components
Usage:
import { createActorContext } from '@xstate/react'; import { someMachine } from './someMachine'; // Create a React Context object that will interpret the machine const SomeContext = createActorContext(someMachine); function SomeComponent() { // Get the current state and `send` function const [state, send] = SomeContext.useActor(); // Or select some derived state const someValue = SomeContext.useSelector((state) => state.context.someValue); // Or get a reference to the actor const actorRef = SomeContext.useActorRef(); return (/* ... */); } function App() { return ( <SomeContext.Provider> <SomeComponent /> </SomeContext.Provider> ); }
3.0.2
Patch Changes
- #3752
4190c3fd6
Thanks @davidkpiano! - Computing the initial state is now consistent withuseMachine
anduseActor
, avoiding stale initial state problems with nested machines
4.0.0-alpha.1
Minor Changes
- #3727
5fb3c683d
Thanks @Andarist! -exports
field has been added to thepackage.json
manifest. It limits what files can be imported from a package - it's no longer possible to import from files that are not considered to be a part of the public API.
Patch Changes
3.0.1
Patch Changes
-
#3456
131d429ab
Thanks @davidkpiano! - AddshallowEqual
helper comparator function. -
#3500
0dfc6d92f
Thanks @Andarist! - Fixed an issue withuseSelector
always computing fresh snapshots internally for uninitialized services. This avoids the internaluseSyncExternalStore
from warning about the snapshot value not being cached properly.
4.0.0-alpha.0
Major Changes
- #3148
7a68cbb61
Thanks @davidkpiano! - RemovedgetSnapshot
parameter from hooks. It is expected that the receivedactorRef
has to have agetSnapshot
method on it that can be used internally.
Patch Changes
- Updated dependencies [
7f3b84816
,969a2f4fc
,c0a6dcafa
,7a68cbb61
,172d6a7e1
,31bc73e05
,e09efc720
,145539c4c
,3de36bb24
,9e10660ec
,8fcbddd51
,515cdc9c1
,6043a1c28
,6a6b2b869
,0b49437b1
,0e24ea6d6
,04e89f90f
,0096d9f7a
,8fcbddd51
,b200e0e0b
,7a68cbb61
,9437c3de9
,0038c7b1e
,7a68cbb61
,b24e47b9e
,390eaaa52
,7a68cbb61
,0c6cfee9a
,e09efc720
,025a2d6a2
,e09efc720
,c99bb43af
,fc5ca7b7f
,c9cda27cb
,5d16a7365
,8fcbddd51
,53a594e9a
,31a0d890f
]:- xstate@5.0.0-alpha.0
3.0.0
Major Changes
-
#2939
360e85462
Thanks @Andarist! - This package now accepts React 18 as a peer dep and the implementation has been rewritten to useuse-sync-external-store
package. This doesn't break compatibility with older versions of React since we are using the shim to keep compatibility with those older versions. -
#2939
360e85462
Thanks @Andarist! -asEffect
andasLayoutEffect
action creators were removed. They were not fitting the React model that well and could lead to issues as their existence suggested that they are easy to use.To execute actions at those exact times you can always either just call your stuff directly from those effects or send events to the machine from those effects and execute explicit actions in response to said events.
-
#2939
360e85462
Thanks @Andarist! - The signatures ofuseMachine
anduseService
integrating with@xstate/fsm
were changed. They now only accept a single generic each (TMachine
andTService
respectively). This has been done to match their signatures with the related hooks that integrate withxstate
itself.
Patch Changes
-
#2939
360e85462
Thanks @Andarist! - In v2 we have changed signatures ofuseMachine
anduseInterpret
. Instead of accepting a list of generics they now only support a single generic:TMachine
. This change, erroneously, was only introduced to types targeting TS@4.x but the types targeting previous TS releases were still using the older signatures. This has now been fixed and users of older TS versions should now be able to leverage typegen with@xstate/react
. -
#2939
360e85462
Thanks @Andarist! -useMachine
forxstate
now correctly rerenders with the initial state when the internal service is being restarted. This might happen during Fast Refresh and now you shouldn't be able to observe this stale state that didn't match the actual state of the service. -
#2939
360e85462
Thanks @Andarist! -useMachine
for@xstate/fsm
now starts the service in an effect. This avoids side-effects in render and improves the compatibility withStrictMode
. -
#2939
360e85462
Thanks @Andarist! - Implementations given touseMachine
targeting@xstate/fsm
are now updated in a layout effect. This avoid some stale closure problems for actions that are executed in response to events sent from layout effects. -
Updated dependencies [
360e85462
,360e85462
]:- @xstate/fsm@2.0.0
2.0.1
Patch Changes
- #3089
862697e29
Thanks @Andarist! - Fixed compatibility with Skypack by exporting some shared utilities from root entry of XState and consuming them directly in other packages (this avoids accessing those things using deep imports and thus it avoids creating those compatibility problems).
2.0.0
Major Changes
-
#2674
e5a8b8dff
Thanks @Andarist, @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.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
ab919d300
Thanks @Andarist! - Removed already deprecateduseService
from@xstate/react
. You can replace its usage withuseActor
.
Patch Changes
- #2957
8550ddda7
Thanks @davidkpiano! - The repository links have been updated fromgithub.com/davidkpiano
togithub.com/statelyai
.
1.6.3
Patch Changes
1.6.2
Patch Changes
-
#2736
2246ae051
Thanks @Andarist, @davidkpiano, @VanTanev! - TheuseSelector(...)
hook now works as expected when theactor
passed in changes. The hook will properly subscribe to the newactor
and select the desired value. See #2702 -
#2685
469268d39
Thanks @farskid, @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 viawithConfig
.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
Patch Changes
- #2587
5aaa8445c
Thanks @Andarist! - Fixed an issue with implementations provided outside of React being wiped out and unusable.
1.6.0
Minor Changes
-
4b4872ca
#2241 Thanks @mattpocock! - Changed the behaviour of guards, delays and activities when declared as options inuseMachine
/useInterpret
.Previously, guards could not reference external props, because they would not be updated when the props changed. For instance:
const Modal = (props) => { useMachine(modalMachine, { guards: { isModalOpen: () => props.isOpen } }); };
When the component is created,
props.isOpen
would be checked and evaluated to the initial value. But if the guard is evaluated at any other time, it will not respond to the props' changed value.This is not true of actions/services. This will work as expected:
const Modal = (props) => { useMachine(modalMachine, { actions: { consoleLogModalOpen: () => { console.log(props.isOpen); } } }); };
This change brings guards and delays into line with actions and services.
⚠️ NOTE: Whenever possible, use data from within
context
rather than external data in your guards and delays.
Patch Changes
-
fe3e859f
#2522 Thanks @farskid, @Andarist! - Fixed an issue with actors not being spawned correctly byuseMachine
anduseInterpret
when they were defined a lazily evaluated context, like for example here:createMachine({ // lazy context context: () => ({ ref: spawn(() => {}) }) });
1.5.1
Patch Changes
453acacb
#2389 Thanks @davidkpiano! - An internal issue where thespawnBehavior
import for theuseSpawn(...)
hook was broken internally has been fixed.
1.5.0
Minor Changes
-
432b60f7
#2280 Thanks @davidkpiano! - Just likeuseInvoke(...)
, other types of actors can now be spawned from behaviors usinguseSpawn(...)
:import { fromReducer } from 'xstate/lib/behaviors'; import { useActor, useSpawn } from '@xstate/react'; type CountEvent = { type: 'INC' } | { type: 'DEC' }; const countBehavior = fromReducer( (count: number, event: CountEvent): number => { if (event.type === 'INC') { return count + 1; } else if (event.type === 'DEC') { return count - 1; } return count; }, 0 // initial state ); const countMachine = createMachine({ invoke: { id: 'count', src: () => fromReducer(countReducer, 0) }, on: { INC: { actions: forwardTo('count') }, DEC: { actions: forwardTo('count') } } }); const Component = () => { const countActorRef = useSpawn(countBehavior); const [count, send] = useActor(countActorRef); return ( <div> Count: {count} <button onClick={() => send({ type: 'INC' })}>Increment</button> <button onClick={() => send({ type: 'DEC' })}>Decrement</button> </div> ); };
1.4.0
Minor Changes
-
849ec56c
#2286 Thanks @davidkpiano! - TheuseService(...)
hook will be deprecated, since services are also actors. In future versions, theuseActor(...)
hook should be used instead:-const [state, send] = useService(service); +const [state, send] = useActor(service);
Patch Changes
ea3aaffb
#2326 Thanks @davidkpiano! - Thesend
type returned in the tuple fromuseActor(someService)
was an incorrectnever
type; this has been fixed.
1.3.4
Patch Changes
aa3c2991
#2223 Thanks @davidkpiano! - Support for actor refs with the.getSnapshot()
method (added for spawned actors in XState version 4.19) is now supported in theuseActor(...)
hook.
1.3.3
Patch Changes
27e7242c
#2112 Thanks @davidkpiano! - TheexecuteEffect
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.
1.3.2
Patch Changes
-
bb5e81ea
#2050 Thanks @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.-import { useMachine } from '@xstate/react/lib/fsm' +import { useMachine } from '@xstate/react/fsm'
1.3.1
Patch Changes
-
b076b253
#1947 Thanks @lukekarrys! - Fix typing of the service returned from the fsm useMachine hook by passing it Typestate -
9b5dc784
#1950 Thanks @Andarist! - Fixed an issue withtoObserver
being internally imported fromxstate/lib/utils
which has broken UMD build and the declared peer dep contract.
1.3.0
Minor Changes
-
577ae023
#1915 Thanks @davidkpiano! - New hook:useInterpret(machine)
, which is a low-level hook that interprets themachine
and returns theservice
:import { useInterpret } from '@xstate/react'; import { someMachine } from '../path/to/someMachine'; const App = () => { const service = useInterpret(someMachine); // ... };
-
577ae023
#1915 Thanks @davidkpiano! - New hook:useSelector(actor, selector)
, which subscribes toactor
and returns the selected state derived fromselector(snapshot)
:import { useSelector } from '@xstate/react'; const App = ({ someActor }) => { const count = useSelector(someActor, (state) => state.context.count); // ... };
1.2.2
Patch Changes
4b31cefb
#1780 Thanks @Andarist! - Fixed an issue with some external packages not being bundled correctly into the UMD bundles.
1.2.1
Patch Changes
a16a5f2f
#1756 Thanks @dimitardanailov! - Fixed an issue withprocess
references not being removed correctly from the UMD bundles.
1.2.0
Minor Changes
dd98296e
#1738 Thanks @dimitardanailov! - Added UMD bundle.
1.1.0
Minor Changes
-
89f9c27c
#1622 Thanks @davidkpiano! - Spawned/invoked actors and interpreters are now typed as extendingActorRef
rather thanActor
orInterpreter
. This unification of types should make it more straightforward to provide actor types in React:import { ActorRef } from 'xstate'; import { useActor } from '@xstate/react'; const Child: React.FC<{ actorRef: ActorRef<SomeEvent, SomeEmitted> }> = ({ actorRef }) => { // `state` is typed as `SomeEmitted` // `send` can be called with `SomeEvent` values const [state, send] = useActor(actorRef); // . .. };
It's also easier to specify the type of a spawned/invoked machine with
ActorRefFrom
:import { createMachine, ActorRefFrom } from 'xstate'; import { useActor } from '@xstate/react'; const someMachine = createMachine<SomeContext, SomeEvent>({ // ... }); const Child: React.FC<{ someRef: ActorRefFrom<typeof someMachine> }> = ({ someRef }) => { // `state` is typed as `State<SomeContext, SomeEvent>` // `send` can be called with `SomeEvent` values const [state, send] = useActor(someRef); // . .. };
1.0.3
Patch Changes
1.0.2
Patch Changes
-
c7927083
#1516 Thanks @davidkpiano! - Thesend
function returned from theuseService()
now can take two arguments (an event type and payload), to match the behavior of@xstate/react
version 0.x. -
db77623a
#1516 Thanks @davidkpiano! - Thesend
value returned from theuseService()
hook will now accept a payload, which matches the signature of thesend
value returned from theuseMachine()
hook:const [state, send] = useService(someService); // ... // this is OK: send('ADD', { value: 3 }); // which is equivalent to: send({ type: 'ADD', value: 3 });
-
93f6db02
#1594 Thanks @Andarist! - Fixed an issue with internalsetState
inuseService
being called with 2 arguments instead of 1. -
72b0880e
#1504 Thanks @Andarist! - Fixed issue withuseService
returning an initial state for services in their final states.
1.0.1
Patch Changes
-
c0bd0407
#1493 Thanks @davidkpiano! - There will now be a descriptive error when trying to use an actor-like object in theuseService()
hook, whereuseActor()
should be preferred:Attempted to use an actor-like object instead of a service in the useService() hook. Please use the useActor() hook instead.
All notable changes to this project will be documented in this file.
[1.0.0-rc.7]
-
The
machine
passed intouseMachine(machine)
can now be passed in lazily:const [state, send] = useMachine(() => createMachine(/* ... */)); // ...
This has the benefit of avoiding unnecessary machine initializations whenever the component rerenders.
-
The
useActor
hook now takes a second argument:getSnapshot
which is a function that should return the last emitted value:const [state, send] = useActor(someActor, (actor) => actor.current);
[1.0.0-rc.6]
[1.0.0-rc.5]
- You can now schedule actions in
useEffect
oruseLayoutEffect
via:asEffect
- queues the action to be executed inuseEffect
asLayoutEffect
- queues the action to be executed inuseLayoutEffect
import { createMachine } from 'xstate';
import { useMachine, asEffect } from '@xstate/react';
const machine = createMachine({
initial: 'focused',
states: {
focused: {
entry: 'focus'
}
}
});
const Input = () => {
const inputRef = useRef(null);
const [state, send] = useMachine(machine, {
actions: {
focus: asEffect(() => {
inputRef.current && inputRef.current.focus();
})
}
});
return <input ref={inputRef} />;
};
[0.8.1]
- Services are now kept up to date
[0.8.0]
- The
useActor()
hook is now available. - Support for persisted states
[0.7.1]
- Actions passed into
useMachine(..., { actions: { ... } })
will now be kept up-to-date and no longer reference stale data.
[0.7.0]
Added
- Machine configuration can now be merged into the options argument of
useMachine(machine, options)
. The following Machine Config options are available:guards
,actions
,activities
,services
,delays
andupdates
(NOTE:context
option is not implemented yet, usewithContext
orwithConfig
instead for the meantime)
const [current, send] = useMachine(someMachine, {
actions: {
doThing: doTheThing
},
services: {
/* ... */
},
guards: {
/* ... */
}
// ... etc.
});