Xstate

by jpeter06

HTML

<script src="https://unpkg.com/xstate@4/dist/xstate.js"></script>
<button onclick="addEvent('next')">
NEXT
</button>

<button onclick="addEvent('reset')">
RESET?
</button>

<div>
state: <span id="state"></span>
</div>

JavaScript

const { createMachine, actions, assign, interpret } = XState;

//Context
const context = { count: 0, max:3 };

// Action
const addCont = assign({ 
  count: (context, event) => context.count + 1
});
function logCont (context, event) { 
  console.log(`After: ${context.count}`)
};
const resetContext = assign({ 
  count: 0
});

// Guard
function isFull(context, event) { console.log("isFull?",context.count)
  return context.count >= context.max;
}

const zpMachine = createMachine({
  id:'zp',
	entry: ['init'], //Se ejecuta al comenzar 
  initial: 'off',
  states: {
    off: {
      on: { 'next': {	target: 'start' ,
      								actions:['addCont', 'logCont'] }, },
    },
    start: {
    	always:{ target: 'awake' ,cond: 'isFull'}, //Condición de paso a nuevo estado!!
      on: { 'next': {	target: 'start' ,            					 
      								actions:'addCont' }, },
    },
    awake: {
      on: {  	'next': {  target: 'walking',    },  
       				'reset': {  target: 'off',    },  
      		},
    },
    walking: {
      on: {  'next': {  target: 'running',    },  },
    },
    running: {
      on: {  'next': {  target: 'off', actions:'resetContext'   },  },
    },
  },
},
  {
    actions: {  addCont , logCont, resetContext},
    guards: {isFull },
  }
);

const zpMachinWC = zpMachine.withContext(context);
const actor = interpret(zpMachinWC).start();
// Fires whenever the state changes
const { unsubscribe } = actor.subscribe((state) => {
	document.getElementById('state').innerHTML = state.value +
  ' count: ' + state.context.count + 
  ' isFull: ' + isFull(state.context);
});

const addEvent = function (event){
	console.log("new Event: ", event);
  actor.send({ type: event});
}