• 8 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 08/02/2024

Déclenchez des effets avec useEffect

Est-ce que je vous ai déjà parlé du render (rendu) d'une application React ?

Dès qu'une modification intervient dans une prop ou le state, le composant concerné et ses enfants sont re-render.

Mais comment faire si on veut effectuer une action qui ne fait pas partie du return ? 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 même pour sauvegarder ce panier à chaque mise à jour ?

Eh bien, ces types d'actions s'appellent des effets de bord, et pour cela, nous avons  useEffect. 😎 Ils nous permettent d'effectuer une action à un moment donné du cycle de vie de nos composants.

Découvrez useEffect

Déclenchez des effets avec useEffect

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.js :

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.js  :

import { useState, useEffect } from 'react'

et utilisez ce snippet à la place (toujours dans  Cart.js) :

useEffect(() => {
    alert(`J'aurai ${total}€ à payer 💸`)
})

Ce qui nous donne pour  Cart.js   :

function 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>
    )
}

Et voilààà ! Tout se passe comme espéré, 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 ?

Nooon ! 😭 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écisez 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.

Cette fonction correspond à l'effet à exécuter. 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 remonter  activeCategory   et  setActiveCategory   et 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.
D'ailleurs, cette question me fait rebondir sur une autre question :

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')
}, [])

Modifiez le titre de votre onglet

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.js, comme ici :

useEffect(() => {
    document.title = `LMJ: ${total}€ d'achats`
}, [total])

Et voilàààà ! Le titre de notre onglet change en fonction du total de notre panier ! 🎉

titre de l'onglet modifié par useEffect
useEffect modifie le titre de notre onglet pour la maison jungle

Maîtrisez les règles de useEffect

Intégrez les différentes étapes de useEffect

Repassons sur ce qu’on vient de voir de useEffect et d’autres utilisations dans cette vidéo !

Intégrez quelques règles

Comme je vous l'ai expliqué au chapitre précédent,  useEffect   est un hook, une fonction qui permet de « se brancher » sur la fonctionnalité des effets de React. Mais 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.

Exercez-vous

Banner Exercez-vous

Nous allons maintenant pouvoir mettre en pratique ce que vous avez appris. Comme toujours, vous trouverez la base de code sur la branche P3C3-Begin.

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()  . Attention, le cart étant maintenant un objet, il vous faudra passer par  JSON.stringify   (vous avez la documentation ici) puis  JSON.parse   (et à nouveau la doc ici) ;

  • 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 avec  localStorage.getItem.

Une fois que vous aurez fini, vous pourrez comparer votre code avec le mien sur P3C3-Solution.

En résumé

  • 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 hook  useEffect   est 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 🎉 Puis, dans la conclusion, nous ferons un petit récapitulatif de ce que vous avez appris, et je vous donnerai quelques pistes pour poursuivre votre apprentissage. Alors à tout de suite ! 😊

Exemple de certificat de réussite
Exemple de certificat de réussite