Les données que nous rendons accessibles aux utilisateurs sont au cœur des applications. Dans la partie précédente, nous avons vu comment manipuler les props à travers les composants, pour les adapter en fonction des données à afficher.
Mais comment faire pour permettre à nos utilisateurs d'interagir avec ces données ? Qu'ils puissent agir sur notre application, entrer des informations, et ainsi modifier les données affichées, et que nous puissions garder les données qu’ils rentrent ?
Vous vous en doutez puisque c'est l'objet de ce chapitre : avec le state !
Nous avions aperçu le state dans la partie précédente, mais c'est maintenant le moment de nous plonger dans le sujet. 👩🚀
Découvrez les stateful components
Le state local est présent à l’intérieur d’un composant et garde sa valeur, même si l'application le re-render. On peut alors dire qu'il est stateful. Vous vous souvenez de notre composant Cart que nous avions créé dans la partie précédente ?
On retourne donc dans Cart.js
. Pour le moment, nous allons uniquement permettre aux utilisateurs d'ajouter des monsteras dans leur panier, supprimons donc tout le reste.
Commençons par importer useState
avec :
import { useState } from 'react'
Puis, on peut créer un state cart
. Avec useState
, nous devons déclarer en même temps une fonction pour mettre à jour ce state ( updateCart
), et lui attribuer une valeur initiale, qui sera ici de 0 :
const [cart, updateCart] = useState(0)
Je vais maintenant pouvoir ajouter un bouton dans mon panier qui permet d'ajouter un monstera avec la fonction que nous venons de déclarer. Ce qui me donne dans Cart.js
:
function Cart() {
const monsteraPrice = 8
const [cart, updateCart] = useState(0)
return (
<div className='lmj-cart'>
<h2>Panier</h2>
<div>
Monstera : {monsteraPrice}€
<button onClick={() => updateCart(cart + 1)}>
Ajouter
</button>
</div>
<h3>Total : {monsteraPrice * cart}€</h3>
</div>
)
}
Maintenant, si on clique sur "Ajouter", le montant total est modifié en fonction du nombre d'éléments sauvegardés dans le state du panier. Lorsqu'un state est modifié, alors l'affichage du composant est rafraichit et la valeur affichée est actualisée, on dit que le composant est re-render.
Bienvenue dans la magie du state ! 🧙♀️ Notre composant Cart est maintenant devenu un stateful component, grâce à useState
.
Concrètement, cela veut dire que le composant Cart peut être re-render autant de fois que nécessaire, mais la valeur du panier sera préservée.
Mais d'ailleurs, useState
, c'est quoi ?
Familiarisez-vous avec useState
useState
est un hook qui permet d’ajouter le state local React à des composants fonctions.
Houlà, un hook ? Qu’est-ce que c’est ?
Un hook est une fonction qui permet de « se brancher » (to hook up) sur des fonctionnalités React. On peut d'ailleurs les importer directement depuis React. Après useState, nous verrons un autre hook dans cette partie : useEffect
. Il existe d'autres hooks que nous n'aborderons pas dans ce cours, mais dans le suivant sur React !
Nous l'avons déjà utilisé, mais je vous le remets ici :
const [cart, updateCart] = useState(0)
Investiguons comment est construit notre state cart. 🧐
Comprenez les crochets
Tout d'abord, les crochets []
. Si cette syntaxe peut vous paraître un peu particulière, il s'agit en fait de la même pratique que nous avions vue dans la partie précédente : la déstructuration. Sauf qu'ici, ça s'appelle la décomposition, parce qu'il s'agit d'un tableau et non d'un objet.
useState
nous renvoie une paire de valeurs dans un tableau de 2 éléments, que nous récupérons dans les variables cart
et updateCart
dans notre exemple. Le premier élément est la valeur actuelle, et le deuxième est une fonction qui permet de la modifier.
Sans la décomposition, nous aurions aussi pu faire :
const cartState = useState(0)
const cart = cartState[0]
const updateCart = cartState[1]
Dans un tableau qu'on décompose, nous pouvons librement nommer nos variables. J'aurais tout aussi bien pu faire :
const [coucou, cavabien] = useState(0)
Initialisez votre state
Intéressons-nous maintenant au paramètre passé entre parenthèses à useState : useState(0)
.
Comme je vous l'ai dit, il correspond à l'état initial de notre state. Cet état initial peut être un nombre comme ici, une string, un booléen, un tableau ou encore un objet avec plusieurs propriétés.
Créez plusieurs variables d'état
Nous allons encore améliorer notre panier. Cette fois-ci, je veux pouvoir choisir de l'afficher ou de le cacher. Pour ça, nous allons utiliser une variable d'état dans notre composant Cart.
Mais il y en a déjà une, comment en créer une autre ? 😱
Pas de panique. Il y a plusieurs moyens de faire. Mais le plus simple est d'utiliser plusieurs variables d'état.
Dans notre cas, il suffit de créer une variable isOpen
associée avec la fonction setIsOpen
, et de l'initialiser à false :
const [isOpen, setIsOpen] = useState(false)
Pour pouvoir interagir, on crée ensuite :
un bouton pour ouvrir le panier qui sera le seul composant retourné par Cart si le panier est fermé ;
et un bouton pour fermer le panier.
Cela nous donne le code suivant :
function Cart() {
const monsteraPrice = 8
const [cart, updateCart] = useState(0)
const [isOpen, setIsOpen] = useState(false)
return isOpen ? (
<div className='lmj-cart'>
<button onClick={() => setIsOpen(false)}>Fermer</button>
<h2>Panier</h2>
<div>
Monstera : {monsteraPrice}€
<button onClick={() => updateCart(cart + 1)}>
Ajouter
</button>
</div>
<h3>Total : {monsteraPrice * cart}€</h3>
</div>
) : (
<button onClick={() => setIsOpen(true)}>Ouvrir le Panier</button>
)
}
En ajoutant un peu de style, j'ai donc :
Vous voyez ? Pas de soucis à créer plusieurs variables d'état dans un même composant ! Alors à vous de jouer ! 💪
Exercez-vous
Comme d'habitude, vous trouverez la base de code pour commencer l'exercice sur la branche P3C1-Begin.
Pour ce chapitre, vous devrez créer un bouton "vider le panier" qui réinitialise le state de notre cart
.
La solution se trouve sur P3C1-Solution.
En résumé
Le state local est présent à l’intérieur d’un composant : ce composant peut être re-render autant de fois que l'on veut, mais les données seront préservées.
Un hook est une fonction qui permet de « se brancher » (to hook up) sur des fonctionnalités React.
useState
est un hook qui permet d’ajouter le state local React à des fonctions composants :Il nous renvoie une paire de valeurs dans un tableau de 2 valeurs, récupérée dans les variables entre crochets.
Il faut initialiser votre state avec un paramètre passé entre parenthèses – un nombre, une string, un booléen, un tableau ou même un objet.
Dans le prochain chapitre, nous allons pousser cette notion de state encore plus loin puisque nous allons apprendre à partager un state entre plusieurs composants. 💪 Ce sera l'occasion d'améliorer notre panier pour qu'il se mette à jour en fonction de la liste de plantes. Plus réaliste, n'est-ce pas ? Alors à tout de suite !