Releases: statelyai/xstate
xstate@5.17.1
Patch Changes
- #5009
51d4c4fc5
Thanks @davidkpiano! - The internal types forStateMachine<...>
have been improved so that all type params are required, to prevent errors when using the types. This fixes weird issues like #5008.
xstate@5.17.0
Minor Changes
-
#4979
a0e9ebcef
Thanks @davidkpiano! - State IDs are now strongly typed as keys ofsnapshot.getMeta()
for state machine actor snapshots.const machine = setup({ // ... }).createMachine({ id: 'root', initial: 'parentState', states: { parentState: { meta: {}, initial: 'childState', states: { childState: { meta: {} }, stateWithId: { id: 'state with id', meta: {} } } } } }); const actor = createActor(machine); const metaValues = actor.getSnapshot().getMeta(); // Auto-completed keys: metaValues.root; metaValues['root.parentState']; metaValues['root.parentState.childState']; metaValues['state with id']; // @ts-expect-error metaValues['root.parentState.stateWithId']; // @ts-expect-error metaValues['unknown state'];
Patch Changes
- #5002
9877d548b
Thanks @davidkpiano! - Fix an issue whereclearTimeout(undefined)
was sometimes being called, which can cause errors for some clock implementations. See #5001 for details.
@xstate/store@2.0.0
Major Changes
- #5000
eeadb7121
Thanks @TkDodo! - - Replaceuse-sync-external-store/shim
withuseSyncExternalStore
from React.- Do not memoize
getSnapshot
inuseSyncExternalStore
. - Implement
getServerSnapshot
inuseSyncExternalStore
. - Expect
store
to always be defined inuseSelector
- Update React types to v18 and testing library to v16.
- Do not memoize
xstate@5.16.0
Minor Changes
-
#4996
5be796cd2
Thanks @ronvoluted! - The actor snapshotstatus
type ('active' | 'done' | 'error' | 'stopped'
) is now exposed asSnapshotStatus
-
#4981
c4ae156b2
Thanks @davidkpiano! - AddedsendParent
to theenqueueActions
feature. This allows users to enqueue actions that send events to the parent actor within theenqueueActions
block.import { createMachine, enqueueActions } from 'xstate'; const childMachine = createMachine({ entry: enqueueActions(({ enqueue }) => { enqueue.sendParent({ type: 'CHILD_READY' }); }) });
xstate@5.15.0
Minor Changes
-
#4976
452bce71e
Thanks @with-heart! - Added exports for actor logic-specificActorRef
types:CallbackActorRef
,ObservableActorRef
,PromiseActorRef
, andTransitionActorRef
.Each type represents
ActorRef
narrowed to the corresponding type of logic (the type ofself
within the actor's logic):-
CallbackActorRef
: actor created byfromCallback
import { fromCallback, createActor } from 'xstate'; /** The events the actor receives. */ type Event = { type: 'someEvent' }; /** The actor's input. */ type Input = { name: string }; /** Actor logic that logs whenever it receives an event of type `someEvent`. */ const logic = fromCallback<Event, Input>(({ self, input, receive }) => { self; // ^? CallbackActorRef<Event, Input> receive((event) => { if (event.type === 'someEvent') { console.log(`${input.name}: received "someEvent" event`); // logs 'myActor: received "someEvent" event' } }); }); const actor = createActor(logic, { input: { name: 'myActor' } }); // ^? CallbackActorRef<Event, Input>
-
ObservableActorRef
: actor created byfromObservable
andfromEventObservable
import { fromObservable, createActor } from 'xstate'; import { interval } from 'rxjs'; /** The type of the value observed by the actor's logic. */ type Context = number; /** The actor's input. */ type Input = { period?: number }; /** * Actor logic that observes a number incremented every `input.period` * milliseconds (default: 1_000). */ const logic = fromObservable<Context, Input>(({ input, self }) => { self; // ^? ObservableActorRef<Event, Input> return interval(input.period ?? 1_000); }); const actor = createActor(logic, { input: { period: 2_000 } }); // ^? ObservableActorRef<Event, Input>
-
PromiseActorRef
: actor created byfromPromise
import { fromPromise, createActor } from 'xstate'; /** The actor's resolved output. */ type Output = string; /** The actor's input. */ type Input = { message: string }; /** Actor logic that fetches the url of an image of a cat saying `input.message`. */ const logic = fromPromise<Output, Input>(async ({ input, self }) => { self; // ^? PromiseActorRef<Output, Input> const data = await fetch(`https://cataas.com/cat/says/${input.message}`); const url = await data.json(); return url; }); const actor = createActor(logic, { input: { message: 'hello world' } }); // ^? PromiseActorRef<Output, Input>
-
TransitionActorRef
: actor created byfromTransition
import { fromTransition, createActor, type AnyActorSystem } from 'xstate'; /** The actor's stored context. */ type Context = { /** The current count. */ count: number; /** The amount to increase `count` by. */ step: number; }; /** The events the actor receives. */ type Event = { type: 'increment' }; /** The actor's input. */ type Input = { step?: number }; /** * Actor logic that increments `count` by `step` when it receives an event of * type `increment`. */ const logic = fromTransition<Context, Event, AnyActorSystem, Input>( (state, event, actorScope) => { actorScope.self; // ^? TransitionActorRef<Context, Event> if (event.type === 'increment') { return { ...state, count: state.count + state.step }; } return state; }, ({ input, self }) => { self; // ^? TransitionActorRef<Context, Event> return { count: 0, step: input.step ?? 1 }; } ); const actor = createActor(logic, { input: { step: 10 } }); // ^? TransitionActorRef<Context, Event>
-
-
#4949
8aa4c2b90
Thanks @davidkpiano! - The TypeGen-related types have been removed from XState, simplifying the internal types without affecting normal XState usage.
xstate@5.14.0
Minor Changes
-
#4936
c58b36dc3
Thanks @davidkpiano! - Inspecting an actor system viaactor.system.inspect(ev => …)
now accepts a function or observer, and returns a subscription:const actor = createActor(someMachine); const sub = actor.system.inspect((inspectionEvent) => { console.log(inspectionEvent); }); // Inspection events will be logged actor.start(); actor.send({ type: 'anEvent' }); // ... sub.unsubscribe(); // Will no longer log inspection events actor.send({ type: 'someEvent' });
-
#4942
9caaa1f70
Thanks @boneskull! -DoneActorEvent
andErrorActorEvent
now contain propertyactorId
, which refers to the ID of the actor the event refers to. -
#4935
2ac08b700
Thanks @davidkpiano! - All actor logic creators now support emitting events:Promise actors
const logic = fromPromise(async ({ emit }) => { // ... emit({ type: 'emitted', msg: 'hello' }); // ... });
Transition actors
const logic = fromTransition((state, event, { emit }) => { // ... emit({ type: 'emitted', msg: 'hello' }); // ... return state; }, {});
Observable actors
const logic = fromObservable(({ emit }) => { // ... emit({ type: 'emitted', msg: 'hello' }); // ... });
Callback actors
const logic = fromCallback(({ emit }) => { // ... emit({ type: 'emitted', msg: 'hello' }); // ... });
Patch Changes
- #4929
417f35a11
Thanks @boneskull! - Expose typeUnknownActorRef
for use when callinggetSnapshot()
on an unknownActorRef
.
@xstate/store@1.0.0
Major Changes
- #4921
f73366504
Thanks @davidkpiano! - Release@xstate/store
version 1.0
xstate@5.13.2
Patch Changes
- #4932
71a7f8692
Thanks @davidkpiano! - Actors with emitted events should no longer cause type issues: #4931
xstate@5.13.1
Patch Changes
-
#4905
dbeafeb25
Thanks @davidkpiano! - You can now use a wildcard to listen for any emitted event from an actor:actor.on('*', (emitted) => { console.log(emitted); // Any emitted event });
@xstate/store@0.0.5
Patch Changes
-
#4918
3323c85a6
Thanks @davidkpiano! - Types are now exported:import type { SnapshotFromStore } from '@xstate/store'; // ...