Le guide de MobX

Découvrez une fantastique bibliothèque de gestion d'état, MobX, et comment l'utiliser dans vos projets React.
La gestion des états est aujourd'hui un sujet important dans toutes les applications. Lorsque nous commençons à définir le strict minimum de notre application, après avoir défini le framework ou la bibliothèque que nous utiliserons, le prochain sujet à définir est la gestion des états.
Nous devons décider: devons-nous utiliser une bibliothèque de gestion d’états? Lequel devrions-nous utiliser?
Nous savons pertinemment que maintenant, dans React, nous avons beaucoup de solutions pour la gestion des états. Nous pouvons utiliser React Hooks, une fonctionnalité publiée dans la version 16.7 qui nous permet de gérer et de traiter nos données d'état dans des composants fonctionnels, ce qui signifie que nous pouvons arrêter d'utiliser des composants de classe uniquement pour la gestion d'état. Ou, nous pouvons utiliser la bibliothèque qui a été la plus largement utilisée dans la communauté React depuis longtemps, Redux.
Mais il y a une autre bibliothèque, pas aussi célèbre que Redux, qui peut nous aider à gérer nos données d'état, et elle
MobX
MobX est une bibliothèque de gestion d'état simple, évolutive et puissante. Tout comme React, qui utilise un DOM virtuel pour rendre les éléments de l'interface utilisateur dans nos navigateurs, réduisant le nombre de mutations DOM, MobX fait la même chose mais dans notre état d'application.
MobX a été créé en utilisant TFRP (application transparente programmation réactive) . Nous pouvons le comprendre comme étant une bibliothèque réactive: cela rend l'état de notre application cohérent et sans bogue en utilisant un graphe d'état de dépendance réactif qui ne sera mis à jour que lorsque cela sera nécessaire.
Une déclaration qui définit très bien MobX est:
Tout ce qui peut être dérivé de l'état de l'application doit être dérivé. Automatiquement.
MobX a de grandes différences avec Redux. Par exemple, dans Redux, nous ne pouvons avoir qu'un seul magasin dans lequel nous stockons toutes nos données d'état; dans MobX, nous pouvons avoir plusieurs magasins à des fins différentes. Une autre grande différence est que, dans Redux, notre état est immuable, alors que dans MobX nous pouvons muter notre état.
Beaucoup de gens aiment expliquer que MobX traite l'état de votre application comme une feuille de calcul, ce qui est vrai. Un autre avantage de MobX est qu'il s'agit d'une bibliothèque indépendante du framework, ce qui signifie que vous pouvez également l'utiliser dans d'autres environnements JS, ou même dans d'autres langages – par exemple, Flutter.
MobX a quatre concepts principaux que nous devrions apprendre , pour comprendre son fonctionnement: observables valeurs calculées réactions et actions .
Observables
Les observables dans MobX nous permettent d'ajouter des capacités observables à nos structures de données – comme des classes, des objets, des tableaux – et de rendre nos propriétés observables. Cela signifie que notre propriété stocke une valeur unique, et chaque fois que la valeur de cette propriété change, MobX gardera une trace de la valeur de la propriété pour nous.
Par exemple, imaginons que nous ayons une variable appelée counter
. Nous pouvons facilement créer une observable en utilisant le décorateur @observable
comme ceci:
import { observable } from "mobx" ];
classe CounterStore {
@observable counter = 0
}
En utilisant le décorateur @observable
nous disons à MobX que nous voulons garder une trace de la valeur du compteur
et chaque fois que le compteur
change, nous obtenons la valeur mise à jour.
Si vous ne souhaitez pas utiliser le décorateur @observable
vous pouvez utiliser décorer
pour rendre votre objet observable:
import { decorate observable } from "mobx" ;
classe CounterStore {
compteur = []
}
décorer ( CounterStore {
compteur : observable
} )
Valeurs calculées
Dans MobX, nous pouvons comprendre les valeurs calculées comme des valeurs qui peuvent être dérivées de notre état, donc le nom «valeurs calculées» a tout son sens. Ce sont essentiellement des fonctions dérivées de notre état, donc chaque fois que notre état change, leurs valeurs de retour changent également.
Une chose dont vous devez vous souvenir à propos des valeurs calculées est que la syntaxe get
est requis, et la dérivation qu'il fait de votre état est automatique – vous n'avez rien à faire pour obtenir la valeur mise à jour.
Pour avoir des valeurs calculées, vous pouvez utiliser le décorateur @computed
comme ceci:
import { observable } from "mobx" ;
class CounterStore {
@ compteur observable = 0
@computed get counterMoreThan100 () {
return this . counter > 100
}
}
Ou, si vous ne voulez pas utiliser le décorateur @computed
vous pouvez également utiliser decorate
:
import { ] observable calculé } à partir de "mobx" ;
class CounterStore {
counter = 0
get counterMoreThan100 () {
return this . counter > [19659028] 100
}
}
décorer ( CounterStore {
compteur : observable
counterMoreThan100 : calculé
} )
Actions
Les actions dans MobX sont un concept très important car elles sont responsables de la modification de notre état. Ils sont responsables de changer et de modifier nos observables.
Pour créer des actions dans MobX, vous pouvez utiliser le décorateur @action
comme ceci:
import { observable } de "mobx" ;
classe CounterStore {
@ compteur observable = 0
@computed get counterMoreThan100 () {
return this . counter > 100
}
@action incrementCounter () {
return this . counter + 1
}
}
Réactions
Les réactions dans MobX sont assez similaires aux valeurs calculées, mais la différence est que les réactions déclenchent des effets secondaires et se produisent lorsque nos observables changent. Les réactions dans MobX peuvent être soit des changements d'interface utilisateur, soit des changements d'arrière-plan – par exemple, une requête réseau, une impression sur la console, etc.
Nous avons les réactions personnalisées: autorun reaction ] quand .
Autorun
Autorun s'exécutera chaque fois qu'un changement observable spécifique. Par exemple, si nous voulions imprimer la valeur du compteur à chaque fois qu'il change, nous pourrions faire comme ceci:
autorun ( () => { ]
console . log ( `Compteur remplacé par: $ { this . counter } ` [19659024])
} )
La réaction autorun reçoit un deuxième argument; ce deuxième argument peut être un objet avec les options suivantes:
delay
: Vous pouvez annuler votre réaction autorun en passant un nombre; si vous ne passez rien, aucun anti-rebond ne se produira.name
: Vous pouvez nommer votre réaction d'exécution automatique en passant une chaîne.onError
: Vous pouvez passer une fonction pour gérer les erreurs de votre réaction d'exécution automatique.scheduler
: Vous pouvez planifier et déterminer si vous souhaitez réexécuter votre fonction d'exécution automatique en la programmant. Il prend une fonction qui devrait être appelée à un moment donné dans le futur, par exemple:{scheduler: run => {setTimeout (run, 1000)}}
.
Reaction
La réaction est très similaire à autorun, mais cela vous donne plus de contrôle sur les valeurs des observables à suivre. Il reçoit deux arguments: le premier est une fonction simple pour renvoyer les données à utiliser dans le second argument. Le deuxième argument sera la fonction d'effet; cette fonction d'effet ne réagira qu'aux données qui ont été passées dans le premier argument de fonction. Cette fonction d'effet ne sera déclenchée que lorsque les données que vous avez transmises dans le premier argument auront changé.
reaction ( () => data [19659021] ( data reaction ) => { sideEffect } options ? ])
Par exemple, créons une réaction pour imprimer dans la console lorsque le compteur est supérieur à 100.
const customReactionCounter = reaction (
([19659024]) => compteur . longueur > 100
counter => console . log ( `Counter is: $ { counter } ` [19659024])
)
La réaction reçoit également un troisième argument, qui peut être un objet avec les options suivantes:
fireImmediately
: C'est une valeur booléenne et elle indique si la fonction doit être déclenchée après la première exécution de la fonction de données.delay
: Vous pouvez annuler votre fonction de réaction en passant un nombre; si vous ne passez rien, aucun anti-rebond ne se produira.est égal à
:comparateur.default
par défaut. Si elle est spécifiée, cette fonction de comparaison sera utilisée pour comparer les valeurs précédentes et suivantes produites par la fonctiondata
. La fonctioneffect
ne sera appelée que si cette fonction renvoie false. Si spécifié, ceci remplaceracompareStructural
.name
: Vous pouvez nommer votre réaction d'exécution automatique en passant une chaîne.onError
: Vous pouvez transmettre une fonction pour gérer les erreurs de votre réaction d'exécution automatique.scheduler
: Vous pouvez planifier et déterminer si vous souhaitez réexécuter votre fonction en la programmant.
The when
Reaction
Of les trois réactions personnalisées de MobX, lorsque
est de loin mon préféré car il est très facile à comprendre lorsque vous apprenez et semble vous donner des super pouvoirs dans votre code.
Le quand
réaction est une fonction qui reçoit deux arguments: le premier est un prédicat qui s'exécutera lorsque la valeur renvoyée est vraie, et le second argument est un effet .
lorsque [19659024] ( prédicat : () => booléen effet ? : () => void options ? )
Alors, par exemple, imaginons que nous avons une réaction lorsque
dans notre code, et chaque fois que la valeur du compteur
est supérieure à 100, nous voulons incrémenter notre compteur. C'est ainsi que nous pouvons faire cela avec la réaction quand
:
classe CounterStore {
constructeur () {
quand (
() => this . counterMoreThan100
() => this . incrementCounter
)
}
@ compteur observable = 0
@computed get counterMoreThan100 () {
return this . counter > 100
}
@action incrementCounter () {
return this . counter + 1
}
}
Maintenant que nous avons appris les quatre concepts principaux de MobX, construisons quelque chose pour que nous puissions les appliquer et apprendre comment tout cela fonctionne dans la pratique.
Premiers pas avec MobX
Nous allons créer un simple application que nous pouvons ajouter et supprimer des livres. Créons donc une nouvelle application create-react-app
.
npx create - react - app mobx - exemple
Installons maintenant les deux dépendances dont nous allons avoir besoin pour utiliser MobX: mobx
et mobx-react
.
yarn add mobx mobx - réagir
Maintenant, nous allons créer notre boutique. Nous allons avoir un observable appelé books
qui sera un tableau de livres, et deux actions: addBook
et removeBook
. N'oubliez pas d'ajouter les décorateurs respectifs: le @observable
décorateur pour les livres et le @action
décorateur pour nos addBook
et removeBook
fonctions.
import { observable action } from 'mobx' ;
class BooksStore [19659021] {
@ livres observables = [] ;
@action addBook = ( book ) => {
this . books . push ( livre )
}
@action removeBook = ( index ) => {
this . books . épissure ( index 1 )
}
}
export default BooksStore
Maintenant que nous avons créé notre boutique, nous devons y avoir accès. Nous allons utiliser le Provider
de mobx-react
donc dans notre fichier index.js
importez simplement le Provider
de mobx-react
et enveloppez notre composant App
comme ceci:
import { Provider } from 'mobx -react ';
< Provider booksStore = { booksStore } >
< App / ]>
< / Provider >
Ce composant Provider
fonctionne à peu près comme le fournisseur Redux. Nous avons un magasin et nous pouvons utiliser ce fournisseur
pour transmettre des magasins en utilisant le mécanisme de contexte de React.
Maintenant, dans notre composant App
importons certaines choses.
import { observer inject } from 'mobx-react' ;
Pour injecter ou connecter nos magasins à notre App
nous allons utiliser inject
. Cela mettra nos magasins (dans notre cas, le booksStore
) à la disposition de notre composant. Nous utiliserons l'observateur
pour rendre réactif notre composant App
ce qui signifie que ce composant suivra les observables que nous utilisons dans notre rendu et le rendra automatiquement à chaque fois que nos observables (dans notre cas, le tableau des livres) change.
Maintenant, nous allons encapsuler notre composant App
avec les deux fonctions, et il ressemblera à ceci:
const App = inject ( [ "booksStore" ] ) ( observateur ( ( { _booksStore_ } : _any_ ) => {
...
} ) ) ;
Créons un div
et à l'intérieur de ce div
nous allons avoir une entrée
et un bouton
. Nous allons utiliser le hook useState
de React pour gérer l'état à l'intérieur de notre composant, juste pour garder une trace de la valeur de l'entrée.
Alors, créons maintenant notre état en utilisant useState
et une nouvelle fonction pour ajouter un livre à chaque fois que nous cliquons sur le bouton.
const [ newBook setNewBook ] = useState ( '' ) ;
const addNewBook = () => {
if (! newBook ) return ;
booksStore . addBook ( newBook ) ;
setNewBook ( "" ) ;
}
Dans notre entrée, nous allons passer le newBook
comme valeur, et une méthode onChange
. Dans notre bouton, nous allons ajouter addNewBook
à exécuter chaque fois que nous cliquons sur le bouton.
< input _type_ = "text" ] _value_ = { newBook } _onChange_ = { ( _e_ ) => setNewBook ( e . target . value ) } / >
< button _onClick_ = { addNewBook } > add < / button >
Nous n'avons aucun livre encore. Mappons maintenant notre tableau books
et pour chaque livre, nous allons ajouter un onClick
pour supprimer un livre.
{ booksStore ]. livres . carte ( ( _book_ _index_ ) => (
< h1 _key_ = { index } _onClick_ = { () => booksStore . removeBook ( index ) } > { book } < / h1 >
) ) }
Notre dernier composant va ressembler à ceci:
const App = inject ] ( [ "booksStore" ] ) ( observateur ( ( { _booksStore_ } [19659024]: _any_ ) => {
const [ newBook setNewBook ] = useState < _string_ > ( '' ) ;
const addNewBook = () => {
if (! newBook ) return ;
booksStore . addBook ( newBook ) ;
setNewBook ( "" ) ;
}
return (
< div >
{ booksStore . books . map ( ] ( _book_ : _string_ _index_ : _number_ ) => (
< h1 _key_ = { index } _onClick_ = { () => booksStore . removeBook ( index ) } > { book }
< / h1 >
) ) }
< input _type_ = "text" _value_ = { newBook } _onChange_ = { ( _e_ : _any_ ) => setNewBook ( e . ] cible . valeur ) } / >
< button _onClick_ = { addNewBook } > add < / button >
< / div >
)
} [19659024]) ) ;
Nous devrions maintenant avoir un composant simple fonctionnant qui nous permet d'ajouter et de supprimer des livres. Comme vous pouvez le voir, MobX est très simple à démarrer et nous pouvons créer des choses puissantes avec. Si vous envisagez de passer à cette bibliothèque, je vous recommande vraiment de le faire.
Conclusion
Dans cet article, nous avons appris comment MobX fonctionne, y compris en quoi il est différent de Redux, ainsi que ses quatre principaux concepts: observables, valeurs calculées, actions, réactions. Et puis nous avons créé un exemple pour le tester dans la pratique.
Source link