Releases: statelyai/xstate
v4.3.3
- 💻 Multiple services now are invoked as expected thanks to @tivac - #367, #368
- 📅 Event object type inference improved. #338
- 🆕 New
StateNode
method:.resolveState(state)
returns a resolved state (with resolved state.value
,.nextEvents
, etc.) in relation to state node (machine):
// partial state
const someState = State.from('red', undefined);
const resolvedState = lightMachine.resolveState(someState);
resolvedState.value;
// => `{ red: 'walk' }`
v4.3.2
v4.3.1
v4.3.0
- 🚚 Improved import/export experience!
The interpreter
is now included in the main module:
- import { interpret } from 'xstate/lib/interpreter';
+ import { interpret } from 'xstate';
As well as common actions, send
, assign
, and sendParent
:
- import { actions } from 'xstate';
- const { send, assign, sendParent } = actions;
+ import { send, assign, sendParent } from 'xstate';
This change is reflected in the documentation as well as the tests.
- ⚛️ Redux DevTools is now supported by XState. This can be turned off/on with the
devTools
property (true
by default):
const service = interpret(someMachine, {
devTools: false // don't show in Redux DevTools
});
ℹ️ Note: JUMP and SKIP actions in the DevTools will have no effect on XState, because there is no reliable way to arbitrarily go from one state to another with state machines, especially if side-effects are executed.
- 👓 Better TypeScript inference for event types is now available thanks to @sangallimarco #303
- 🏷 Service IDs will now take the ID of the machine if one is not specified:
const machine = Machine({ id: 'foo', /* ... */ });
// ...
{
invoke: {
// Invoked child service will have .id === 'foo'
src: machine
}
}
- 📖 Lots of documentation updates, especially with Invoking Services.
- 🐛 Fixed bugs: #326, #329, #331
v4.2.4
- 🕵️ Anonymous functions (including arrow functions) as actions are no longer silently ignored, and are executed. #298
- 💥 New method on services:
.execute(state)
will execute the state's actions (defined onstate.actions
). #295 - 📖 Documentation updates:
- Forbidden transitions
- Transient state nodes
- Various formatting/fixes
- 🕐 State history is correctly disposed now, to prevent memory leaks.
- ☎️ Second argument to invoked callbacks,
onEvent
, now let you register event listeners for when the machine sends events directly to the invoked callbacks. (docs coming 🔜) - 🚦 Activities are now properly disposed when a service is stopped.
v4.2.3
v4.2.2
- 📚 New & updated docs:
- 🔬
state.changed()
logic fixed to better determine if a state actually changed. - 💥 Action order corrected to properly execute nested final state actions before parent final state actions. #273
v4.2.1
- 📚 Lots of documentation updates: https://xstate.js.org/docs
- 💥 Added the
.event
property toState
instances, so you can know which event caused the transition to the currentState
:
const lightMachine = Machine({ /* ... */ });
const currentState = lightMachine.transition('green', 'TIMER');
console.log(currentState.event);
// => { type: 'TIMER' }
- 👪 Fixed #269 by ensuring two things:
- Services invoked on the parent machine (which are alive for the lifetime of the machine, FYI) are successfully invoked when the machine is started
- Starting activities (such as
invoke
, which is an activity) should be executed before executingonEntry
actions.
v4.2.0
- ➕ Added CODE_OF_CONDUCT.md
- 💙 Added Webflow as a sponsor
- 📖 Added documentation directly to the
master
branch for easier maintenance (in the/docs
directory) - The
send(...)
action creator now accepts an "event expression", which is a function that providescontext
andevent
as arguments and returns anEvent
:
import { actions } from 'xstate';
const { send } = actions;
// contrived example
const sendName = send((ctx, event) => ({
type: 'NAME',
name: ctx.user.name
}));
Only use this when necessary - a static argument, e.g., send({ type: 'FOO' })
is still preferred (because it's more deterministic). This follows the <send>
SCXML spec for the eventexpr
attribute.
This also works with sendParent(eventExpr)
.
- 🆕 Added the
state.inert
getter property onState
instances, which represents a state as-is without actions. - #️⃣ Targets can now be represented as getters that return references to
StateNodes
rather than string IDs:
const lightMachine = Machine({
// ...
states: {
green: {
on: {
get TIMER() {
return lightMachine.states.yellow;
}
}
},
yellow: { /* ... */ }
}
});
This is completely optional, and useful when if you want to avoid strings or have stricter typings.
- 🔧 Strict machines (
strict: true
) will no longer throw errors for built-in events, such asdone.state.*
ordone.invoke.*
events. - 📞 Now you can
invoke
a service that can send multiple events back to the parent via a callback:
// ...
states: {
counting: {
invoke: {
src: (ctx, event) => (callback) => {
const interval = setInterval(() => {
// sends 'SOME_EVENT' to parent on interval
callback('SOME_EVENT');
}, ctx.interval);
return () => clearInterval(interval);
}
}
}
}
// ...
This makes it easy to communicate with streams of events (such as Observables) through invoke
. Note that since there can be an infinite number of events, it's not assumed that a callback interval will call onDone
. Instead, you have to manually send doneInvoke(id)
via the callback
(this will be in the docs 🔜).
- ⛔️ An interpreted machine (service) will now throw an error if the initial state given to it is invalid.
v4.1.1
.npmignore
was removed ❌- The
"files"
property was added instead to ensure only the desired files show up in the NPM package.