- πββοΈ Custom guards are now supported. Read the docs π:
SEARCH: {
target: 'searching',
// Custom guard object
cond: {
type: 'searchValid',
minQueryLength: 3
}
}
- βοΈ Delay expressions are now supported. Read the docs π and see #244 for a use-case:
states: {
green: {
after: {
// after 1 second, transition to yellow
LIGHT_DELAY: 'yellow'
}
},
// ...
// Machine options
{
// String delays configured here
delays: {
LIGHT_DELAY: (ctx, e) => {
return ctx.trafficLevel === 'low' ? 1000 : 3000;
},
YELLOW_LIGHT_DELAY: 500 // static value
}
}
- βοΈ New package:
@xstate/react
provides you theuseMachine
hook from the docs. Read the README π
import { useMachine } from '@xstate/react';
import { myMachine } from './myMachine';
export const App = () => {
const [current, send] = useMachine(myMachine);
// ...
}
- π§ Redux DevTools now defaults to
false
in the console, in order to prevent random crashes of the extension. To activate it, set{ devTools: true }
in the interpreter options:
// default: { devTools: false }
interpret(machine, { devTools: true });
- βΉ Activities are no longer started in transient states. This is because transient states are essentially zero-time, since statecharts should transition to the resolved state immediately, so the activities would be started and stopped in the same microstep anyway.
- π
nextEvents
will now be properly populated inState
objects when transitioning from a state value rather than an existingState
object (or when restoring a saved state). - βΉοΈ Action implementations can now read the current state (this should not be a common use-case):
actions: {
log: (ctx, e, { action, state }) => {
console.log(state); // logs the State instance
}
}
- β¬οΈ TypeScript version bumped up to 3.3.3333
- β Ever experience those annoying errors about sending events to an uninitialized service? Maybe you forgot to
.start
it, or maybe you know it will be initialized and something out of your control (e.g., React's rendering) initializes the service right after you send an event to it. Now, events are deferred by default and will queue up in the uninitialized service until the service is.start()
-ed... and then the events are processed. A warning will still show up to let you know that the service wasn't initialized.- If you prefer the original behavior, set
interpret(machine, { deferEvents: false })
in the interpreter options.
- If you prefer the original behavior, set
- π₯ Services will now resolve the
State
(or state value) that they are started with, which means you can:
// Start a service from a restored state
someService.start(State.from({ bar: 'baz' }))
// Or from a plain state value
someService.start({ bar: 'baz' });
// Even if the state value is unresolved!
// (assume 'baz' is the initial state of 'bar')
someService.start('bar'); // resolves to State.from({ bar: 'baz' })
- πState changes now properly detect context changes. #397
- π Relative child transitions that are external (
{ internal: false }
) now properly exit and reenter the parent state before transitioning to the child state; .e.g,{ target: '.child', internal: false }
will now behave like{ target: 'parent.child' }
. #376 - βοΈ Delayed transitions are now properly canceled after a service is stopped.
- β An awesome React calculator demo based on the original calculator statechart by Ian Horrocks was added to the docs. Thanks, Mukesh Soni!
- π If an invoked Promise throws, it will only send an event if the Promise wasn't canceled. #379