Closed rudijs closed 6 years ago
What code were you trying to use?
@xaviergonz This code is still experimental for me I'm new to both xstate and MST.
Here's the model I have, it's pretty simple with just two model properties - name and currentState.
The currentState is derived from the xstate State Chart, I would like this property to be observable.
The state is transitioning from one to the other in an MST action, which is called by the application using the MST.
import { types } from "mobx-state-tree";
import { Machine } from "xstate";
// visualizer: https://musing-rosalind-2ce8e7.netlify.com/
const stateChart = {
initial: "idle",
states: {
idle: {
on: {
LOADING: "loading"
}
},
loading: {
on: {
SUCCESS: "active",
INACTIVE: "inactive",
REJECTED: [
{
target: "inactive.rejected"
// target: "inactive"
}
],
ERROR: [
{
target: "inactive.noConnection"
// target: "inactive"
}
]
}
},
inactive: {
on: {
LOADING: "loading"
},
states: {
rejected: {
data: {
details: "Identity request rejected"
}
},
noConnection: {
data: {
details: "Cannot connect to Scatter"
}
}
}
},
active: {
on: {
FORGET_IDENTITY: "loading"
}
}
}
};
const identityMachine = Machine(stateChart);
export const Identity = types
.model({
name: types.string,
currentState: identityMachine.initialState.value
})
.views(self => ({
get isAuthenticated() {
return self.name === "Get Scatter" ? false : true;
}
}))
.actions(self => ({
stateTransition(state) {
self.currentState = identityMachine.transition(
self.currentState,
state
).value;
},
setSession(identity) {
if (!identity) {
self.name = "Get Scatter";
return;
}
self.name = identity.name;
}
}))
.extend(self => {
let scatter = null;
return {
views: {
get scatter() {
return scatter;
}
},
actions: {
setScatter(value) {
scatter = value;
}
}
};
});
When the model property currentState
changes from string to object, MST throws.
const TInactive = types.model({
inactive: types.string
})
const CurrentState = types.union("loading", "active", "inactive", TInactive)
export const Identity = types
.model({
name: types.string,
currentState: types.optional(CurrentState, identityMachine.initialState.value)
})
However I'd move indentityMatchine to the env of the node at creation time, or to a volatile, but up to you
@xaviergonz Sweet! Thank you very much.
I was very stuck, your reply nails it plus offers up some flexibility on the modeling approachs I can now take.
@xaviergonz Of the serveral approaches possible and following your suggested solution, I'm currently happy with this working solution:
There are states
and nested states
. Nested states allow more fine tuned and informative app/component states.
So I've got these two types separate for code clarity:
export const identityMachine = Machine(stateChart);
// states
const Tstates = types.enumeration(["idle", "loading", "active", "inactive"]);
// nested states
const TnestedStates = types.model({
inactive: types.string
});
export const Identity = types
.model({
name: types.string,
currentState: types.union(Tstates, TnestedStates)
})
the identityMachine
is exported so with the MST is instantiated in index.js
(main) it's done like so:
import { Identity, identityMachine } from "./models/Identity";
const identityState = Identity.create({
name: "Get Scatter",
currentState: identityMachine.initialState.value
});
identityState
is now the MST that is used in the React app.
For that I'm using mobx-react
's Provider
and inject
for different components as required.
Question
Hi,
I'd like to create a model with a property that can be a type string or a type object.
I'm using xstate and the currentState could be:
The object form represents nested state in xstate.
In order to transition from one state to the next I need to pass in either the string or the object.
MST blows up when I try to pass in a object when a string has already been inferred.
I was looking at union types, but I'm a bit stuck and can't seem to figure it out.
Is it possible to model this type of MST model property?
Thanks.