ember-statechart-component icon indicating copy to clipboard operation
ember-statechart-component copied to clipboard

How to work with "state"?

Open MichalBryxi opened this issue 11 months ago • 4 comments

Hi,

I can see that for xstate matches there is a shorthand in ember-statechart-component:

<Toggle as |toggle|>
  (toggle.matches 'inactive')
</Toggle>

From the official xstate documentation it seems like it should also work in this way:

<!-- This does not work -->
<Toggle as |toggle|>
  (toggle.snapshot.matches 'inactive')
</Toggle>

But this does not work with:

Uncaught TypeError: Cannot read properties of undefined (reading 'value')

And respective this(?) is there set to undefined:

Screenshot 2024-12-22 at 17 33 54 (screenshot tests step1, but it's supposed to be inactive in the example above)

I came to this conclusion from an ability to access context on snapshot which works for me:

<Toggle as |toggle|>
  {{toggle.snapshot.context.isActive}}
</Toggle>

I do not necessarily care about how do I call state.matches as there is a way, but I wanted to access state.can and possibly other functions, but it does not work for me.

MichalBryxi avatar Dec 22 '24 16:12 MichalBryxi

aye, that's a bug with glimmer-vm, which (when fixed) will also unlock: https://github.com/emberjs/rfcs/pull/1045

NullVoxPopuli avatar Dec 22 '24 16:12 NullVoxPopuli

tracking issue: https://github.com/glimmerjs/glimmer-vm/issues/1652

NullVoxPopuli avatar Dec 22 '24 16:12 NullVoxPopuli

I do not necessarily care about how do I call state.matches as there is a way, but I wanted to access state.can and possibly other functions, but it does not work for me

I ran into this same problem trying to use tags. It seems like you should be able to do something like this:

<Toggle as |toggle|>
  {{if (toggle.snapshot.hasTag "on") "ON" "not ON"}}
</Toggle>

But this doesn't seem to work for me. I worked around it by creating a helper function and doing it in JS:

const hasTag = (x, tag: string) => {
  return x.snapshot.hasTag(tag);
};
<Toggle as |toggle|>
  {{if (hasTag toggle "on") "ON" "not ON"}}
</Toggle>

I tried can, and it will work as well:

const can = (x, eventType: string) => {
  return x.snapshot.can({ type: eventType });
};
<Toggle as |toggle|>
  {{if (can toggle "TOGGLE") "can toggle" "cannot toggle"}}
</Toggle>

So it works, but these (and a couple other little things) are just enough friction to have me going back to using xstate directly instead of the component.

tcjr avatar Apr 08 '25 20:04 tcjr

yea, sorry I haven't fixed the VM yet :( waiting on some syntax changes in https://github.com/glimmerjs/glimmer-vm/pull/1690

NullVoxPopuli avatar Apr 08 '25 20:04 NullVoxPopuli