XState
- enumerate only the possible states to remove impossible states on your app video
Graph Theory
different type of nodes:
- Source nodes: nodes with no incoming edges
- Transfer nodes: nodes that have both incoming and outgoing edges
- Sync mode: nodes with no outgoing edges
Finite states
- "you can be awake or sleep, but you CAN'T be sleep and awake at the same time"
- Transitions are the edges
- Events are the labels that needs to happen in order to transition from one state to another (from node to node)
- There's only one initial state and ONLY one initial state
- Final states: states where no more events can happen. is "Accepted"
Modeling state machines
- first add the states
- then we can start filling events
example of a simple machine:
1const machine = {2 initial: "inactive",3 states: {4 inactive: {5 on: {6 CLICK: "active",7 },8 },9 active: {10 on: {11 CLICK: "inactive",12 },13 },14 },15};
you can also write state transitions in two ways:
1const machine = {2 initial: "inactive",3 states: {4 inactive: {5 on: {6 CLICK: "active", // shorthand of `target`7 },8 },9 active: {10 on: {11 CLICK: {12 target: "inactive",13 },14 },15 },16 },17};
here's is how it looks a state machine
1// let's use a lightbulb example...23// states are objects4const lit = {};5const unlit = {};6const broken = {};78// then we can combine our states in one object9const states = { lit, unlit, broken };1011// we need an initial state12const initial = "unlit";1314// then we can also combine states and initial state (config) and this is what we can pass to our state machine15const config = {16 id: "lightBulbMachine", // the config should have an ID17 initial,18 states,19};
Now we need to enumerate all the possible events that our machine can handle. In order to do that, we need to define on every state the possible events that can be triggered to change the state, we do it with the on
property on our state objects
1const lit = {2 on: {3 BREAK: "BROKEN",4 TOGGLE: "unlit",5 },6};7const unlit = {8 on: {9 BREAK: "BROKEN",10 TOGGLE: "lit",11 },12};13const broken = {};14// because broken is the final state, we can leave the state object empty, but we can also add a `type: 'final'` on it to make it more explicit
by convention, the name of the event is capitalize, and the value of the event is the target state name we want to transition to.
Now we are ready to import the XState library to test it.
Actions
- is a side-effect. this effects are considered the outputs of the state machine
Three types of actions:
- Transition actions: when transitions from one state to another
- Entry actions: when you enter a particular state
- Exit actions: when leaving a particular state
the order of the actions will be executed are:
- Exit actions
- Transition actions
- Entry actions
- In general, don;t want to depend on action order too much. if you find yourself depending on the order too much, that's a sign that you need to model it different and maybe add an extra state
this is how actions looks like in XState:
1const machine = createMachine(2 {3 initial: "inactive",4 states: {5 inactive: {6 entry: () => {}, // this could be an array of functions too7 on: {8 CLICK: {9 target: "active",10 actions: ["someAction", () => {}],11 },12 },13 },14 active: {15 // ...16 },17 },18 },19 {20 actions: {21 someAction: () => {},22 },23 }24);
- the second parameter (the actions object) will override any actions inside the ones defined in the machine
- finite states represents Qualitative data, it describes the behaviour
Extended state
- describes Quantitative data. The combination of both (Finite + Extended state) describes your state machine
- in XState is called
context
Assignments
- are actions
- are pure fucntions. you need to get the prev state
Resources
1