menu

Statecharts

The Statecharts community on Spectrum is (along with spectrum) MOVING TO OTHER PLATFORMS: For statecharts discussions in general go to Statecharts Discussion on GitHub (link) or Gitter (link). For XState-specific questions, go to the XState discussion forum for Q&A or the Stately discord chat to chat.

Channels
Team

Statecharts watercooler

March 7, 2019 at 5:55am
Show previous messages

August 18, 2020 at 12:24am
notEnoughCookies: {
on: {
EAT: { target: 'checkCookies', actions: 'eatCookie' }
}
},
checkCookie: {
always: [
{ target: 'enoughCookies', cond: 'hasEnoughCookies' },
{ target: 'notEnoughCookies' }
]
},
enoughCookies: { type: 'final' }
I guess? seems a little verbose.
Edited
  • reply
  • like

August 18, 2020 at 1:15pm
It's verbose on purpose. There are two "states" in reality: the state where you executed the action, and the state where you are checking which state you should transition to based on that executed-action state.
  • reply
  • like
You can always make it less verbose by creating helper functions, since it's just a plain JS object. Nothing special there.
  • reply
  • like

August 20, 2020 at 8:49pm
So I have what I assume is a very typical use case, I have a modal flow where the user can choose to login, signup or click "forgot password". I model this as a statechart with two nested charts, one about the account creation process and another about the reset password flow (logging in is just part of the main chart)
  • reply
  • like
Since the account creation state is nested, I thought I would store context data in there (i.e. your personal data or whatever), however I can't seem to do that. It appears I am forced to have that context in the parent machine
  • reply
  • like
so the parent machine just has an initial state and can go to an "account_creation" state, which is the subchart. Inside the account_creation subchart, you can go back to the parent's "initial" state if you are in the account creation screen, but if you get past it, you can't go back anymore.
  • reply
  • like
const creation = {
initial: 'account_data',
context: {
// I want to read this
name: 'test',
some_data: 123
},
states: {
account_data: {
on: {
BACK: '#acct.initial',
NEXT: 'personal_data'
},
},
personal_data: {
on: {
NEXT: 'address'
}
},
address: {
on: {
BACK: 'personal_data',
NEXT: 'payment_data'
}
},
payment_data: {
on: {
BACK: 'address'
},
},
}
}
const machine = Machine({
id: 'acct',
initial: 'initial',
context: {
foo: 0
},
states: {
initial: {
on: {
CREATE: 'creation'
}
},
creation: {
on: {
NEXT: 'finish'
},
...creation
},
finish: {
type: "final"
}
}
});
  • reply
  • like
How can I get access to the child state? Do I have to pollute the main machine with that somewhat irrelevant state? Should I create separate machines (but then how do I go back)?
  • reply
  • like
or do I simply not use context at all, and instead use the local state of my component (I'm using react)
  • reply
  • like

October 16, 2020 at 10:51am
I was not able to understand how I can update context data by using external objects. Could some one please provide an example. I'm new to both React and xstate. I was not able to understand how to update the context
  • reply
  • like
Got it. We can update the data from the event...Thanks.
  • reply
  • like

October 27, 2020 at 10:19am
Hello everyone, I want to fetch data then update context every n seconds. But the code below doesn't work, any tips? thanks
activities: {
queryRoundStatus: (context) => {
const timer = setInterval(() => {
logger.log(`queryRoundStatus, inteval: ${HEART_BEAT_INTERVAL}`)
API.queryRoundStatus(context.gameId)
.then(data => assign({ ...data }))
}, HEART_BEAT_INTERVAL);
return () => clearInterval(timer)
},
},
  • reply
  • like
I think you would need to separate getting the data & saving the data to context. You could use a callback, then, when the callback fires, have a seperate action to save the response data to state. Here is an example of a callback that might help - https://bradwoods.io/guides/xstate/invoke-callback
  • reply
  • like
thanks, it works well.
  • reply
  • like
so I can only update context with actions, is that true?
  • reply
  • like
(simon-lu) ... more precisely, I believe I remember reading somewhere in the docs that the only way to update context is using actions.assign. The only other way I can think of is by "extending" an existing machine using withContext. I find that particularly useful when spawning child machines.
Edited
  • reply
  • like
(simon-lu) Try this:
invoke: {
src: () => (sendBack) => {
const interval = setInterval(() => sendBack({ type: 'HEARTBEAT' }), 1000)
return () => clearInterval(interval)
}
},
on: {
HEARTBEAT: { /* ... do whatever ... */}
}
  • reply
  • like
Hey there! Is there no way to get useMachine in vue2?
  • reply
  • like
I mean I can write my own implementation of it, but was just wondering if there isn't an official vue2 package for it
  • reply
  • like

October 28, 2020 at 2:42pm
That's currently in the works. Have you tried the way referenced in the docs?
  • reply
  • like
I'm not sure what way that would be? :)
  • reply
  • like
that's what I'm using, but that doesn't provide an interface to override things like services on a per-case basis?
  • reply
  • like

November 6, 2020 at 4:01pm
Would anyone have a good example of how to connect graphQL subscriptions to a state machine? Currently I'm subscribing in a Vue component and sending the result to the state machine to store in its context, but ideally I would want any data fetching/subscribing to be done in the machine instead, so my component can just be an expression of the context/state
  • reply
  • like

November 9, 2020 at 11:23pm
Using Typescript... if I spawn another machine as an actor and save the ref in context, how should I type it?
I have ServerMachine which spawns instances of SocketMachine and saves them in a sockets array in the context - but what should the type of the array be?
  • reply
  • like
Show more messages