
Est-ce que je vous ai déjà parlé du render (rendu) d'une application React ?
Mais comment faire si on veut effectuer une action qui ne fait pas partie du return ?
Une action qui intervient après que React a mis à jour le DOM ? Par exemple, si vous voulez déclencher une alerte à chaque fois que votre panier est mis à jour ? Ou bien sauvegarder ce panier dans le navigateur ?
Eh bien, ces types d'actions s'appellent des effets de bord, et pour cela, nous avons useEffect. Il nous permet d'effectuer une action à un moment donné du cycle de vie de nos composants.
Essayons dès maintenant ! Disons que je veux créer une alerte lorsque j'ajoute une plante à mon panier, et que cette alerte affiche le montant total du panier.
Pour ça, une petite ligne de code suffit dans Cart.jsx :
alert(`J'aurai ${total}€ à payer 💸`)On la met donc directement dans notre composant, avant le return. Allez-y, essayez !
Quand je clique, ça bloque mon code et ma valeur ne s'affiche qu'une fois que j'ai cliqué sur "OK" ! Qu'est-ce qui se passe ?
Pas de panique ! Faites-moi confiance : nous n'allons pas en rester là.
À la place, on va utiliser useEffect.
Importez-le comme nous l'avons fait avec useState dans Cart.jsx :
import { useState, useEffect } from 'react'et utilisez ce snippet à la place (toujours dans Cart.jsx) :
useEffect(() => {
alert(`J'aurai ${total}€ à payer 💸`)
})Ce qui nous donne pour Cart.jsx :
import { useState, useEffect } from 'react'
const Cart = ({ cart, updateCart }) => {
const [isOpen, setIsOpen] = useState(true)
const total = cart.reduce(
(acc, plantType) => acc + plantType.amount * plantType.price,
0
)
useEffect(() => {
alert(`J'aurai ${total}€ à payer 💸`)
})
return isOpen ? (
<div className='lmj-cart'>
<button
className='lmj-cart-toggle-button'
onClick={() => setIsOpen(false)}
>
Fermer
</button>
{cart.length > 0 ? (
<div>
<h2>Panier</h2>
<ul>
{cart.map(({ name, price, amount }, index) => (
<div key={`${name}-${index}`}>
{name} {price}€ x {amount}
</div>
))}
</ul>
<h3>Total : {total}€</h3>
<button onClick={() => updateCart([])}>
Vider le panier
</button>
</div>
) : (
<div>Votre panier est vide</div>
)}
</div>
) : (
<div className='lmj-cart-closed'>
<button
className='lmj-cart-toggle-button'
onClick={() => setIsOpen(true)}
>
Ouvrir le Panier
</button>
</div>
)
}
export default CartEt voilà ! Tout se passe comme prévu, pour la simple et bonne raison que useEffect nous permet d'effectuer notre effet une fois le rendu du composant terminé.
Et comme useEffect est directement dans notre composant, nous avons directement accès à notre state, à nos variables, nos props ; magique n'est-ce pas ?
Mais attendez, qu'est-ce qui se passe si je ferme mon panier ?
Non ! Mon alerte se déclenche aussi !
Eh bien c'est normal : je vous ai dit que useEffect se déclenche après le rendu. Eh bien il se déclenche après CHAQUE rendu du composant. Sauf si vous préciser quand déclencher un effet avec le tableau de dépendances…
Pour décider précisément quand on veut déclencher un effet, on peut utiliser le tableau de dépendances. Il correspond au deuxième paramètre passé à useEffect.
Ici, il s'agit de :
() => {
alert(`J'aurai ${total}€ à payer 💸`)
}Le deuxième paramètre de useEffect accepte un tableau noté entre crochets : il s'agit du tableau de dépendances.
Dans notre cas, si je veux que l'alerte ne s'affiche que lorsque le total de mon panier change, il me suffit de faire :
useEffect(() => {
alert(`J'aurai ${total}€ à payer 💸`)
}, [total])Vous pouvez mettre n'importe quelle variable ici. Si vous voulez afficher l'alerte quand le total change OU quand une nouvelle catégorie est sélectionnée, vous pourriez tout à fait :
récupérer la catégorie sélectionnée (en faisant remonteractiveCategoryetsetActiveCategoryet en les passant en props) ;
puis mettre[total, activeCategory]dans votre tableau de dépendances.
Essayez pour voir !
L'alerte s'affiche bien quand la catégorie change ou bien quand le total change.
Et... est-ce que l'effet est lancé au tout premier render de mon composant ?
Essayez de rafraîchir la page pour voir ! L'alerte s'affiche. Donc la réponse est oui.
Mais d'ailleurs, comment faire pour exécuter un effet uniquement après le premier render de mon composant ? Par exemple, si je veux récupérer des données sur une API ?
Eh bien, dans ce cas, il faut renseigner un tableau de dépendances vide :
useEffect(() => {
alert('Bienvenue dans La maison jungle')
}, [])Bon, moi je commence à en avoir un peu marre de toutes ces alertes. J'ai plutôt envie d'utiliser useEffect pour mettre à jour le titre de l'onglet de mon navigateur.

Vous voyez de quoi je parle ?
On va donc utiliser document.title toujours dans Cart.jsx:
useEffect(() => {
document.title = `LMJ: ${total}€ d'achats`
}, [total])Et voilà ! Le titre de notre onglet change en fonction du total de notre panier !

useEffect modifie le titre de notre onglet pour la maison jungle.
useEffectMais quelques règles particulières s'appliquent au hook useEffect :
Appelez toujours useEffect à la racine de votre composant. Vous ne pouvez pas l'appeler à l'intérieur de boucles, de code conditionnel ou de fonctions imbriquées. Ainsi, vous vous assurez d'éviter des erreurs involontaires.
Comme pour useState, useEffect est uniquement accessible dans un composant fonction React. Donc ce n'est pas possible de l'utiliser dans un composant classe, ou dans une simple fonction JavaScript.
Par ailleurs, je vous conseille de séparer les différentes actions effectuées dans différents useEffect. Cela est plutôt une bonne pratique qu'une règle.

Nous allons maintenant pouvoir mettre en pratique ce que vous avez appris.
Ici, vous allez permettre à l'utilisateur de garder son panier, même lorsqu'il rafraîchit la page. Pour cela, nous allons utiliser localStorage.
Afin d'assurer la meilleure expérience utilisateur possible, vous devez :
Sauvegarder le panier à chaque modification avec localStorage.setItem()
Vous assurer que le panier n'est pas sauvegardé plus de fois que nécessaire.
Récupérer le panier au premier chargement de la page aveclocalStorage.getItem
useEffectpermet d'effectuer des effets : cela permet à notre composant d'exécuter des actions après l'affichage, en choisissant à quel moment cette action doit être exécutée.
Le hookuseEffectest appelé après chaque rendu de votre composant. Il est possible de préciser quelle modification de donnée déclenche les effets exécutés dans useEffect, avec le tableau de dépendances.
Un tableau de dépendances vide permet d'exécuter un effet uniquement au premier rendu de votre composant.
Félicitations à vous ! Vous avez presque terminé ce cours : il ne vous reste qu'un quiz. Bonne chance !