Skip to content

v4.7.0

Compare
Choose a tag to compare
@davidkpiano davidkpiano released this 30 Nov 15:44
  • 🐌 If a subscriber/listener subscribes to a service that is already running, it will now receive the current state upon subscription. #814
  • 🆙 The new escalate() action creator escalates custom error events to a parent machine, which can catch those in the onError transition:
import { createMachine, actions } from 'xstate';
const { escalate } = actions;

const childMachine = createMachine({
  // ...
  // This will be sent to the parent machine that invokes this child
  entry: escalate({ message: 'This is some error' })
});

const parentMachine = createMachine({
  // ...
  invoke: {
    src: childMachine,
    onError: {
      actions: (context, event) => {
        console.log(event.data);
        //  {
        //    type: ...,
        //    data: {
        //      message: 'This is some error'
        //    }
        //  }
      }
    }
  }
});
  • ❓ You can now specify undefined as the first argument for machine.transition(...), which will default to the initial state:
lightMachine.transition(undefined, 'TIMER').value;
// => 'yellow'
  • 🤝 Services (invoked machines) are now fully subscribable and can interop with libraries that implement TC39 Observbles like RxJS. See https://xstate.js.org/docs/recipes/rxjs.html for more info.

  • 🆔 When a service is invoked, it has a uniquely generated sessionId, which corresponds to _sessionid in SCXML. This ID is now available directly on the state object to identify which service invocation the state came from: state._sessionid #523

  • ⚙️ The original config object passed to Machine(config) (or createMachine(config)) is now the exact same object reference in the resulting machine.config property.

  • 🎰 The createMachine() factory function now exists and is largely the same as Machine(), except with a couple differences:

    • The generic type signature is <TContext, TEvent, TState> instead of <TContext, TStateSchema, TEvent>.
    • There is no third argument for specifying an initial context. Use .withContext(...) on the machine or return a machine with the expected context in a factory instead.
  • 🛑 Event sent to a stopped service will no longer execute any actions, nor have any effect. #735

  • 🚸 The invoked actors are now directly available on state.children.

  • ✍️ Plain strings can now be logged in the log() action creator:

entry: log('entered here', 'some label')
const quietMachine = Machine({
  id: 'quiet',
  initial: 'idle',
  states: {
    idle: {
      on: {
        WHISPER: undefined,
        // On any event besides a WHISPER, transition to the 'disturbed' state
        '*': 'disturbed'
      }
    },
    disturbed: {}
  }
});

quietMachine.transition(quietMachine.initialState, 'WHISPER');
// => State { value: 'idle' }

quietMachine.transition(quietMachine.initialState, 'SOME_EVENT');
// => State { value: 'disturbed' }