menu
Channels
Team
Posts
Chat
Members
Info
Show previous messages

October 21, 2019 at 1:47am
The "runner" code I am using is basically this:
  • reply
  • like
async function run(machine, dispatchTable, completionCallback) {
let currentState = machine.initialState;
let service = interpret(machine);
service.options.sync = true;
service
.onTransition(async state => {
currentState = state;
if (state.changed == undefined || state.changed == true) {
if (state.value in dispatchTable) {
var transition = await dispatchTable[state.value](state)
service.send(transition.value, transition.data)
}
}
})
.onDone(() => { completionCallback(currentState) })
.start();
}
  • reply
  • like

October 21, 2019 at 4:27pm
Hey guys I'm having some issue with action invocation in the folowing FMS:
module.exports = {
id: 'runner',
initial: 'setup',
states: {
setup: {
on: {
RECEIVED: {
target: 'running',
actions: ['runTask'],
},
ERROR: {
target: 'error',
actions: ['taskError'],
},
TERMINATED: {
target: 'terminated',
actions: ['terminate'],
},
},
},
running: {
on: {
COMPLETE: {
target: 'complete',
actions: ['taskComplete'],
},
ERROR: {
target: 'error',
actions: ['taskError'],
},
TERMINATED: {
target: 'terminated',
actions: ['terminate'],
},
},
},
terminated: {
type: 'final',
},
complete: {
type: 'final',
},
error: {
type: 'final',
},
},
}
The actual machine is created and started in external TASK() class. Like this:
if (!this.state) this.state = interpret(Machine(require('./task_statemachine'), {
actions: {
runTask: this.runTask,
taskComplete: this.taskComplete,
taskError: this.taskError,
terminate: this.terminate
}
})).start();
The events are send using this.state.send('COMPLETE');, but the actions never run. I don't see anything wrong with the code, what's the possible cause of this behaviour? Do I need to invoke actions as callbacks ? e.g runTask: this.runTask()
  • reply
  • like
this might be problematic.
  • reply
  • like
If i remove this. it becomes just a word instead of reference to the function, which result in ReferenceError: runTask is not defined
  • reply
  • like
If I define actions like this runTask: this.runTask() it becomes a callback and seems to run correctly, but it's a bad practice AFAIK.
  • reply
  • like
have you tried setting strict to true? If you send COMPLETE to the machine above it will be ignored if the machine is in the "setup" state. Setting strict to true would kick out exceptions on invalid transitions, otherwise they are quietly ignored
  • reply
  • like
Tried just now makes the difference. The class constructor is loaded, but the machine seemingly never starts.
  • reply
  • like
^ makes no difference
  • reply
  • like
Right, I'm just saying that it is probably not an XState issue but a scope resolution issue?
  • reply
  • like
Would you mind clarifying? The machine is created / started in constructor of TASK() class, all functions are defined in the same class, I don't see what would cause issues with scope.
  • reply
  • like
David - I posted an example over in the "general" channel. Could you take a look at it? If I can solve this issue of nested FSMs I'll be very happy.
  • reply
  • like
Also I would be happy to pitch in to improve docs. They're pretty vague in a few places.
  • reply
  • like
  • reply
  • like
David - I posted an example over in the "general" channel. Could you take a look at it? If I can solve this issue of nested FSMs I'll be very happy.
Link please?
  • reply
  • like
  • reply
  • like

October 30, 2019 at 1:44pm
Hello everyone! I'm looking into using xstate but I can't find the answer to this question: is it possible to express different context types based of state? Conceptually my states look like this:
type State = { state: 'state1', data: string } | { state: 'state2', data: number };
I know that I can't have data of type number when my state is 'state1' but I don't think I can represent that through context.
Is this supported in xstate?
  • reply
  • like

October 31, 2019 at 2:08am
you might use xState 'meta' to hold static data, or else set up your context to parallel state1 and state2 so that you store both data types separately.
Edited
  • reply
  • like
looks like almost exactly what I need. Can I set metadata from an event?
  • reply
  • like

October 31, 2019 at 6:10pm
Can I set metadata from an event?
That would defeat the purpose of having static meta data. You would use context if you wanted to do that.
  • reply
  • like

November 1, 2019 at 7:04am
Oh, I guess I misunderstood. Basically what I need is different context for each state, like an OR type in TypeScript:
type State = { state: 'idle', context: IdleData } | { state: 'inProgress', context: InProgressData };
^ in this example idle context and in progress context do not overlap at all, so having one context for them would be messy. Do you have any tips for handling this use case ?
  • reply
  • like
Right now I'm putting data for each state in a separate context key, so my context looks like this:
type Context = { idle?: IdleData, inProgress?: InProgressData };
But this is not ideal because it's not clear from the type that idle and inProgress are mutually exclusive, which I think will eventually lead to bugs.
  • reply
  • like

November 18, 2019 at 4:13pm
Hey! I just ran into an issue with transitions with wildcard events. They don't seem to work - or maybe I'm missing something? My use case involves parallel states so maybe that's a specific issue there, but could someone please try and explain why the following doesn't work? https://xstate.js.org/viz/?gist=a0fb6640cd19a7519498316595118d33
  • reply
  • like
I can never seem to get to the .other state
  • reply
  • like

November 19, 2019 at 12:24am
Wildcard transitions don't work in 4.6 - the visualizer is still using the stable version
  • reply
  • like