XState est une bibliothèque permettant de créer, d'interpréter et d'exécuter des machines à états finis et des diagrammes d'états, ainsi que de gérer les invocations de ces machines en tant qu'acteurs. Les concepts informatiques fondamentaux suivants sont importants pour savoir comment faire le meilleur usage de XState, et en général pour tous vos projets logiciels actuels et futurs.
Cela tombe bien car lorsque nous avons réalisé Jerry, l'application de blagues qui vous propose de rire entre amis nous avons eu besoin de gérer des transitions d'états pour gérer les différentes phases qui s'enchainent pour le jeu.
Dans cet article nous allons détailler comment ont été modélisés les états et les transitions entre les 3 phases de jeu d'une des premières version de Jerry :
Comme nous le suggère la méthodologie pour déterminer une machine à état commençons par définir la liste des états, les évènements (permettant de déclencher les transitions) et l'état initial.
Et le contexte, qui sont des variables sur lesquelles on peut agir, parfois aussi nommé état, mais au sens plus large.
current_joke nous permet de récupérer une chaine de caractères qui représente notre blague actuelle, color sert à donner la couleur de fond utilisée pour afficher la blague, celle-ci est tirée aléatoirement à chaque cycle et enfin teams_score sert à définir l'avatar de chaque équipe ainsi que le nombre de points dans la partie.
Commençons par partager le code de notre machine et expliquons chaque éléments les uns après les autres.
Le truc bien avec XState c'est que l'on peut utiliser le vizualizer pour récupérer un diagramme représentant les états et transitions de notre machine. Pour le code ci-dessus, voici le diagramme obtenu.
Pour plus de détails et de contrôle il est possible de suivre ce lien pour consulter le diagramme en détails.
Tout d'abord on définit deux interfaces Typescript qui nous servirons à définir d'une part le contexte (équivalent de l'état qui peut changer) de notre machine, comme vu plus haut, mais également les évènements qui permettront de déclencher les transitions, grâce à cela on obtient un typage sécurisé en utilisant la généricité de la méthode createMachine.
Ensuite, on continue en donnant un identifiant à la machine avec la clé id, cela sert à des fins de debug. Un état initial, dans notre cas choose_joke et un contexte par défaut qui sera probablement surchargé afin que l'on puisse injecter de la donnée.
S'en suit la définition de nos différents états, commençons par choose_joke
On voit ici que plusieurs hooks sont définis :
Ensuite nous avons invoke, ce qu'on appelle un service dans XState.
Enfin nous avons la clé on qui permet de définir les réponses aux évènements qui correspondent à notre définition.
Ici très simple, on utilise l'instruction after pour définir une période de temps après laquelle on exécutera une action. Dans notre cas c'est un changement d'état vers choose_loser.
Encore une fois on utilise une référence textuelle vers la configuration de la machine mais on aurait pu simplement passer la durée en clé (ce qui est moins pratique mais plus simple pour tester).
Ici, selon l'environnement React Native que l'on soit en mode développement ou production la durée est raccourcie à 2 secondes au lieu de 10 secondes pour développer plus facilement.
On atterri ensuite dans la phase de choix du perdant, où si quelqu'un à rigolé durant la phase précédente il fait marquer un point à l'équipe adverse.
Ici on utilise encore l'instruction on sauf qu'on y rajoute un paramètre sous forme de tableau.
XState va évaluer dans l'ordre les éléments en y appliquant la condition définie et cond et référencée en option de la machine. Lorsqu'une condition sera bonne XState s'arrêtera et exécutera les actions définies dans le bloc.
Dans notre cas on vérifie si l'évènement à reçu un argument avec la référence vers le perdant, si c'est le cas on adapte le score en cohérence, sinon on migre simplement vers l'étape choose_joke
Maintenant que l'on a réussi à définir notre machine à états, comment utiliser cette dernière avec React ? Et bien c'est très simple grâce à la librairie pour react fournie par XState.