-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Beta-release] useMachine
#241
Conversation
Tryin' it out: NullVoxPopuli/emberclear#803 |
addon/usables/use-machine.js
Outdated
createUsable(context, { machine }) { | ||
const owner = getOwner(context); | ||
|
||
const interpreter = new InterpreterService(machine); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should check if this is a Machine
or MachineConfig
and create a Machine
, if machine
is a MachineConfig
(to eliminate the need for side-effecting code in module-space -- as the XState docs have by default (cause it's easier to teach that way))
|
||
setup() { | ||
this.service = interpret(this.machine, { | ||
clock: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this clock here? / what's it for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://xstate.js.org/api/classes/interpreter.html#clock
The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.
We are making sure that we use the ember runloop when the xstate-interpreter schedules delays, transitions et al. This is important when we are testing etc.
get state() { | ||
return { | ||
currentState: this.currentState, | ||
send: this.service.send, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about transition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.service
refers to an interpreted machine - i.e. a xstate-Interpreter. In contrast to a Machine
an Interpreter
has no transition
-method only a send
-method. You just send events to an interpreter and the interpreter then figures out if it needs to transition into a new state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I had just gotten confused with remembering my own code. I have a transition component action that just calls send
will try - not entirely sure how to type this yet but I'll do my best |
Overall looks awesome, I'll give this a try on the weekend 🚀 |
}, | ||
"devDependencies": { | ||
"@ember/optional-features": "^1.3.0", | ||
"@ember/render-modifiers": "^1.0.2", | ||
"@glimmer/component": "^1.0.0", | ||
"@glimmer/tracking": "^1.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is moving this to dependencies
intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we're good with dropping support for pre 3.15, I'd assume so ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I moved it because we use it in the usable. 🤔 will recheck
addon/usables/use-machine.js
Outdated
|
||
get state() { | ||
return { | ||
currentState: this.currentState, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we name this state
it's aligned to xstate/react
and xstate/vue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just.. current
? since the getter is already state
? we have the mental context that we're already getting the "state", but current
would just mean the current version of it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we name this state it's aligned to
xstate/react
and
xstate/vue
I was thinking the same as I saw that 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, ignore me. I thought this was used in a different way. I'm 👍 on state
addon/index.js
Outdated
return function () { | ||
return { | ||
get() { | ||
return xstateMatchesState(state, this[statechartPropertyName].currentState.value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still the only thing that doesn't sit right with me -- mostly because it's relying on an implicit property name.
I wonder if it makes sense to do something like:
class Foo {
@use myInterpreter = useMachine(machineStuff);
@matches(this.myInterpreter, 'someState');
isSomeState;
}
idk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how this works already.
class Foo {
@use myInterpreter = useMachine(myMachine);
@matchesState('busy', 'myInterpreter')
isBusy;
}
If you leave out the default property it checks the statechart
-property. I think best is to make this this default property name configurable via a setting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if possible to pass a 'this' property to a decorator, that would make the most sense intuitively, but I don't know if the decorators are evaluated before instantiation.
My gut on this is that matchesState is for a very imperitive style of consuming statecharts, and I think we should survey some people outside of the xstate community for feedback :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what you mean by imperative style for consuming. matchesState
is reactive getter for matching against state patterns - it's just a decorator that makes it more ergonomical (arguably) to match against the current-state of the interpreter.
You could also do this when you wanted to react to state changes but @matchesState
saves you some typing.
// @matchesState is literally doing the same thing
get isBusy() {
return matchesState('busy', this.statechart.state.value);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what you mean by imperative style for consuming.
Just that there is a magic, undeclared relationship with the property name of the useMachine value.
You could also do this when you wanted to react to state changes but @matchesState saves you some typing.
I think that's more inline with modern JS. Though, I'd switch the args:
get isBusy() {
return matchesState(this.statechart.state.value, 'busy');
}
or even:
get isBusy() {
return this.statechart.state.match('busy');
}
@NullVoxPopuli @pangratz updated PR with tests for |
c351208
to
b07eb81
Compare
index.d.ts
Outdated
type Send<Context, Schema, Events extends EventObject> = Interpreter<Context, Schema, Events>['send']; | ||
|
||
type InterpretedUsable<Context, Schema, Events extends EventObject> = { | ||
currentState: State<Context, Events>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be updated as well
Just tried with embroider, and am currently getting this error:
Still investigating, but want to document here as it may be relevant for someone in the future. |
instead of in the Interpreter Service
…er things if desired (except the clock)
Co-authored-by: Clemens M�ller <[email protected]>
We want to be as aligned with other xstate framework wrappers as possible thus we from now on will use the same naming scheme as `xstate/react` and `xstate/vue`.
* rename currentState to state * expose this.service in types
2d0e112
to
479b42b
Compare
@pangratz @NullVoxPopuli can you please recheck the PR? - getting ready to release |
useMachine
useMachine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BEAUTIFUL 🚢 🇮🇹
@NullVoxPopuli @pangratz This is now in and released as 0.10.0. Thanks for participating and all the help from both of you 👏 |
YAPADAPADUUUUUU |
Fixes #235
Todos:
useMachine(this.args.machine)
and figure out how to handle this - right nowuse
would resetup the interpreter which probably isn't something usefulwithConfig
orwithContext
Releases on npm to try this out:
0.10.0-beta.0