Closed martaver closed 6 years ago
For normal routing, check out the example here: https://state-machine-yzgnuxxwmg.now.sh/
For nested routes, that's a good question - and also a good reason to avoid tying business logic to the UI (which is hard, since React tends to want to colocate business logic with actual UI, though this can cause problems in the long run).
We've been discussing nested statechart encapsulation here: https://spectrum.chat/?t=de76a10c-32f5-4377-a51f-5ba61c451081 and to clarify, whenever you have a "black box" 3rd party component (or route, in this case) that has its own state machine, in development code, this should simply be treated as a provider of values to the parent statechart (think dispatch
in redux) and handled as external state.
This probably requires more thought, and the reason it's difficult to find a suitable API for this (at least at the moment) is because whereas parts of the user interface might be completely encapsulated in terms of code (e.g., 3rd-party components or API calls), there is no such thing as encapsulation to the user using the user interface. Everything is within context; everything is on the same screen; all pixels are equal to the user, and 3rd-party components are very much a part of the same app, and don't "feel" like 3rd-party components.
With that insight, a testing statechart would need to be able to assume the behavior of 3rd-party components, but a development statechart might not (that is, an encapsulated statechart might just be a provider of values, like an event emitter/listener). Something to think about.
However, now I'm thinking - ideally, a component should be able to know, and enumerate, a finite representation of its possible rendered child components. Those child components might have static statecharts, that can be provided to the parent before the component is initiated:
import Foo from './components/foo';
import Bar from './components/bar';
const machine = Machine({
initial: 'foo',
states: {
foo: {
...Foo.machine,
on: {
NEXT: 'bar',
PREV: 'foo'
}
},
bar: {
...Bar.machine,
on: {
NEXT: 'bar',
PREV: 'foo'
},
}
}
});
class App extends React.Component {
static machine = machine;
// ...
render() {
// ...
// renders either <Foo /> or <Bar />
}
}
I'm going to play around with the above idea - it seems the most idiomatic and the least "black-boxy". The goal of statecharts is to model application behavior and logic as comprehensively as possible, because it essentially needs to "think" like a user using the app would think.
Any thoughts around this, @michelebertoli?
I've had a lot of success decoupling routing logic from the UI in my react projects, using router5 instead of react-router.
In a perfect world, routing
is simply another state and has nothing to do with UI. The other domains of application state include data
(obtained from an API, for e.g.) and ui
. I imagine the 'data' state as a normalized data set and the ui as, for example, an xstate machine. We reselect/combine from these three domains to make props for components.
Having the router separate from other concerns works beautifully, because it means we can attach behavior to route transitions freely before their signal reaches any components. I imagine a similar approach could work with xstate, but how would it cross over? E.g.
How would route params (parsed from url) be passed to our state machines? Would route transitions be treated as a first-class state transition when navigating? Would route transitions simply invoke necessary state transitions as side-effects?
How would route params (parsed from url) be passed to our state machines?
Do you mean in the context of conditional transitions? You'd pass that data (the extended state) in as the third argument to machine.transition(...)
, see the docs: http://davidkpiano.github.io/xstate/docs/#/guides/guards
Would route transitions simply invoke necessary state transitions as side-effects?
That's one way of approaching it, yeah. URL routing is a perfect example of a finite state machine, though xstate
isn't "specialized" for routing, but can be used for it. Consider the transition()
function just as a way of telling you "what is the next state?" That's the only difference you'd make in your routing approach - instead of imperatively telling the router where to go, you first ask xstate
what the next route will be given the current state and the action just taken. Everything else is solved just as you would solve it without any extra libraries.
Hello @Martaver @davidkpiano, the static machine property is an interesting approach for nested (encapsulated) machines.
One of the most powerful features of statecharts is the possibility to zoom in and zoom out. So, in this scenario, the top level states represent the routes and each router transition is also a xstate
transition of the statechart which is controlling the entire application.
If you have any more questions on this topic, feel free to open a new issue 😄
i am a new in xState and also stuck on same point from last 2 days and didn't found any clue to navigate/map routes between screens in react native app.Like i have login screen and when i successfully login i need to navigate on home screen with same machine' state logic.Another thing i didn't understand that when i trying to create a instance of via useMachine() in home screen it will reset machine state to initial state.
@tv-ravi Want to open this as a discussion instead?
There's nothing special about routing + XState, since XState is agnostic to routing, but I'd love to see your code to get a better idea of what you're trying to do.
Thanks for an inspiring talk! I'm fascinated with the idea of expressing UIs as automata and I'm really keen to take xstate on a test run in a small project. I'm wondering, though, as to how I would integrate this state machine with a route hierarchy.
Each route, I imagine, would be an immediate entry point to a default state associated with it... perhaps the transitions would also transition the route state where appropriate... would each route contain its own state machine, orthogonal from each other route's state machine? How would this nest?
I would love to hear your opinions on the topic!