github statelyai/xstate xstate@5.0.0-alpha.2

latest releases: @xstate/vue@4.0.0, @xstate/store@2.6.1, @xstate/svelte@4.0.0...
pre-release19 months ago

Major Changes

  • #3837 61553600b Thanks @davidkpiano! - Actors are now always part of a "system", which is a collection of actors that can communicate with each other. Systems are implicitly created, and can be used to get and set references to any actor in the system via the systemId prop:

    const machine = createMachine({
      // ...
      invoke: {
        src: emailMachine,
        // Registers `emailMachine` as `emailer` on the system
        systemId: 'emailer'
      }
    });
    const machine = createMachine({
      // ...
      entry: assign({
        emailer: (ctx, ev, { spawn }) => spawn(emailMachine, { systemId: 'emailer' })
      })
    });

    Any invoked/spawned actor that is part of a system will be able to reference that actor:

    const anotherMachine = createMachine({
      // ...
      entry: sendTo(
        (ctx, ev, { system }) => {
          return system.get('emailer');
        },
        { type: 'SEND_EMAIL', subject: 'Hello', body: 'World' }
      )
    });

    Each top-level interpret(...) call creates a separate implicit system. In this example example, actor1 and actor2 are part of different systems and are unrelated:

    // Implicit system
    const actor1 = interpret(machine).start();
    
    // Another implicit system
    const actor2 = interpret(machine).start();
  • #3911 d638a0001 Thanks @davidkpiano! - The self actor reference is now available in all action metas. This makes it easier to reference the "self" ActorRef so that actions such as sendTo can include it in the event payload:

    // Sender
    actions: sendTo('somewhere', (ctx, ev, { self }) => ({
      type: 'EVENT',
      ref: self
    })),
    
    // ...
    
    // Responder
    actions: sendTo((ctx, ev) => ev.ref, ...)
  • #3743 30c561e94 Thanks @davidkpiano! - Restoring persisted state is now done by passing the state into the state: ... property of the interpret options argument:

    -interpret(machine).start(state);
    +interpret(machine, { state }).start();

    The persisted state is obtained from an actor by calling actor.getPersistedState():

    const actor = interpret(machine).start();
    
    const persistedState = actor.getPersistedState();
    
    // ...
    
    const restoredActor = interpret(machine, {
      state: persistedState
    }).start();
  • #3889 b394cf188 Thanks @davidkpiano! - Autoforwarding events is no longer supported and the autoForward property has been removed.

    Instead of autoforwarding, events should be explicitly sent to actors:

    invoke: {
      id: 'child',
      src: 'someSrc',
    - autoForward: true
    },
    // ...
    on: {
      // ...
    + EVENT_TO_FORWARD: {
    +   actions: sendTo('child', (_, event) => event)
    + }
    }
  • #3815 66bc88a68 Thanks @davidkpiano! - The interpret(...) function now accepts input in the second argument, which passes input data in the "xstate.init" event:

    const greetMachine = createMachine({
      context: ({ input }) => ({
        greeting: `Hello ${input.name}!`
      }),
      entry: (_, event) => {
        event.type; // 'xstate.init'
        event.input; // { name: 'David' }
      }
      // ...
    });
    
    const actor = interpret(greetMachine, {
      // Pass input data to the machine
      input: { name: 'David' }
    }).start();
  • #3743 30c561e94 Thanks @davidkpiano! - Invoked actors can now be deeply persisted and restored. When the persisted state of an actor is obtained via actor.getPersistedState(), the states of all invoked actors are also persisted, if possible. This state can be restored by passing the persisted state into the state: ... property of the interpret options argument:

    -interpret(machine).start(state);
    +interpret(machine, { state }).start();
  • #3915 9e18af130 Thanks @davidkpiano! - The actor.onTransition(...) method has been removed in favor of .subscribe(...)

     const actor = interpret(machine)
    -  .onTransition(...)
    -  .start();
    +actor.subscribe(...);
    +actor.start();
  • #3877 1269470bd Thanks @davidkpiano! - Observing an actor via actor.subscribe(...) no longer immediately receives the current snapshot. Instead, the current snapshot can be read from actor.getSnapshot(), and observers will receive snapshots only when a transition in the actor occurs.

    const actor = interpret(machine);
    actor.start();
    
    // Late subscription; will not receive the current snapshot
    actor.subscribe((state) => {
      // Only called when the actor transitions
      console.log(state);
    });
    
    // Instead, current snapshot can be read at any time
    console.log(actor.getSnapshot());
  • #3878 bb9103714 Thanks @davidkpiano! - Actors can no longer be stopped directly by calling actor.stop(). They can only be stopped from its parent internally (which might happen when you use stop action or automatically when a machine leaves the invoking state). The root actor can still be stopped since it has no parent.

  • #3884 aa80811e5 Thanks @davidkpiano! - Custom action objects and guard objects are now expected to put extra parameters on the params property:

    actions: {
      type: 'sendMessage',
    - message: 'hello'
    + params: {
    +   message: 'hello'
    + }
    }
    guard: {
      type: 'exists',
    - prop: 'user'
    + params: {
    +   prop: 'user'
    + }
    }
  • #3924 c4e58c88d Thanks @davidkpiano! - The fromReducer(...) function is now called fromTransition(...).

  • #3890 326937415 Thanks @davidkpiano! - The state._sessionid property has been removed. It should be obtained directly from the actor: actor.sessionId.

  • #3756 67d576190 Thanks @Andarist! - All transitions became internal by default. The style of the target pattern (.child, sibling, #id) has now no effect on the transition type.

    Internal transitions don't reenter their source state when the target lies within it. You can still create external transitions (ones that reenter the source state under the mentioned circumstances) by explicitly setting external: true on the given transition.

Don't miss a new xstate release

NewReleases is sending notifications on new releases.