logo oujood
🔍

useContext : Partagez des Données Globales Sans Props Drilling

OUJOOD.COM

Introduction

Le Hook `useContext` est utilisé pour accéder aux données d'un contexte React dans un composant fonctionnel. Il permet de partager des données globales (comme des thèmes ou des informations utilisateur) entre plusieurs composants sans avoir besoin de les passer via des props ("props drilling").

Dans ce chapitre, nous allons explorer :

  • Qu'est-ce qu'un Contexte en React ?
  • Comment créer et utiliser un Contexte avec `useContext`.
  • Des exemples pratiques pour illustrer son fonctionnement.

1. Qu'est-ce qu'un Contexte en React ?

Un contexte React est un mécanisme qui permet de partager des données entre plusieurs composants sans avoir besoin de les passer manuellement via des props. Cela est particulièrement utile pour les données globales telles que :

  • Thème de l'application : Par exemple, mode sombre ou clair.
  • Informations utilisateur : Comme le nom ou l'état de connexion.
  • Langue sélectionnée : Pour les applications multilingues.

Avant les Hooks, seuls les composants basés sur des classes pouvaient utiliser le contexte via la méthode `contextType`. Avec `useContext`, cette fonctionnalité est désormais disponible pour tous les composants fonctionnels.

2. Création d'un Contexte

Voici comment créer un contexte React et l'utiliser avec `useContext` :

📋 Copier le code

import React, { createContext, useContext, useState } from 'react';
import { createRoot } from 'react-dom/client';

// Création du Contexte
const ThemeContext = createContext('light'); // Valeur par défaut : "light"

// Composant Fils qui utilise le contexte
function BoutonTheme() {
    const theme = useContext(ThemeContext); // Accède au contexte via useContext

    return (
        <button style={{ backgroundColor: theme === 'dark' ? '#333' : '#f9f9f9', color: theme === 'dark' ? 'white' : 'black' }}>
            Thème actuel : {theme}
        </button>
    );
}

// Composant Parent qui fournit le contexte
function App() {
    const [theme, setTheme] = useState('light');

    function changerTheme() {
        setTheme(theme === 'light' ? 'dark' : 'light');
    }

    return (
        <ThemeContext.Provider value={theme}>
            <div>
                <h1>Gestion de Contexte avec useContext</h1>
                <BoutonTheme />
                <button onClick={changerTheme}>Changer de thème</button>
            </div>
        </ThemeContext.Provider>
    );
}

const root = createRoot(document.getElementById('root'));
root.render(<App />);
        

Explication détaillée ligne par ligne :

  1. import React, { createContext, useContext, useState } from 'react'; :
    • Nous importons React ainsi que les Hooks createContext, useContext, et useState.
    • createContext est utilisé pour créer un contexte React.
    • useContext permet d'accéder aux données du contexte dans un composant fonctionnel.
    • useState gère l'état local du composant parent.
  2. const ThemeContext = createContext('light'); :
    • Cette ligne crée un contexte appelé ThemeContext avec une valeur par défaut ('light').
    • Si aucun fournisseur de contexte n'est défini, tous les composants utilisant ce contexte recevront la valeur par défaut.
  3. function BoutonTheme() { ... } :
    • Ce composant fils utilise le Hook useContext pour accéder aux données du contexte.
    • Il affiche dynamiquement le thème actuel et ajuste son apparence selon cette valeur.
  4. const theme = useContext(ThemeContext); :
    • Cette ligne utilise useContext pour récupérer la valeur actuelle du contexte ThemeContext.
    • theme représente la valeur du contexte (par exemple, 'light' ou 'dark').
  5. <button style={{ backgroundColor: theme === 'dark' ? '#333' : '#f9f9f9', color: theme === 'dark' ? 'white' : 'black' }}> :
    • Ce bouton change dynamiquement son arrière-plan et sa couleur de texte en fonction de la valeur du contexte theme.
    • backgroundColor: theme === 'dark' ? '#333' : '#f9f9f9' : Si le thème est 'dark', l'arrière-plan devient noir (#333); sinon, il reste blanc (#f9f9f9).
    • color: theme === 'dark' ? 'white' : 'black' : Si le thème est 'dark', le texte devient blanc; sinon, il reste noir.
  6. function App() { ... } :
    • Ce composant parent fournit le contexte ThemeContext à ses enfants via ThemeContext.Provider.
    • Il gère également l'état local theme avec useState.
  7. <ThemeContext.Provider value={theme}> :
    • ThemeContext.Provider est utilisé pour fournir la valeur actuelle du contexte (theme) à tous les composants enfants.
    • value={theme} spécifie la valeur du contexte (par exemple, 'light' ou 'dark').
  8. function changerTheme() { ... } :
    • Cette fonction alterne entre les thèmes 'light' et 'dark'.
    • setTheme(theme === 'light' ? 'dark' : 'light') met à jour l'état theme en inversant sa valeur actuelle.
  9. root.render(<App />); :
    • Rend le composant App dans l'élément HTML ayant l'id root.
    • Utilise createRoot pour garantir une compatibilité avec React 18 et versions ultérieures.

3. Avantages de `useContext`

Utiliser `useContext` offre plusieurs avantages significatifs par rapport au passage de props manuel ("props drilling") :

  • Élimination du Props Drilling : Vous pouvez partager des données globales sans avoir besoin de les transmettre via chaque niveau de composant intermédiaire.
  • Simplification du Code : Les composants peuvent directement accéder aux données du contexte, réduisant ainsi la complexité du code.
  • Maintenabilité : Les mises à jour du contexte sont centralisées, facilitant la maintenance et la mise à jour des données globales.

4. Exemple Concret : Application Multilingue

Imaginons que vous souhaitez créer une application multilingue où chaque composant peut accéder à la langue sélectionnée via un contexte. Voici comment cela peut être fait :

Le code qui suivra est un exemple simple illustrant l'utilisation de React Context et du hook useContext pour gérer la langue dans une application React.

1. Création et Fourniture du Contexte

  • Création du contexte :
    const LangueContext = createContext('fr'); // Valeur par défaut : "fr"

    On crée un contexte nommé LangueContext avec pour valeur par défaut 'fr'. Cette valeur est utilisée lorsqu'aucun Provider n’est présent dans l’arborescence.

  • Fourniture du contexte :

    Dans le composant App, on utilise le Provider associé pour transmettre la valeur du contexte à tous les composants enfants :

    <LangueContext.Provider value={langue}>
      {/* ... */}
    </LangueContext.Provider>
          

    Ici, la valeur passée au Provider est gérée par le state local langue.

2. Consommation du Contexte

Dans le composant enfant Salutation, le hook useContext permet d’accéder à la valeur actuelle du contexte :

  function Salutation() {
  const langue = useContext(LangueContext);

  return (
    < >
      {langue === 'fr' ? 'Bonjour' : 'Hello'} !
    < />
  );
}
 

Selon la langue (fr ou en), le composant affiche « Bonjour » ou « Hello ».

3. Gestion de l'État et Interaction

Le composant App utilise le hook useState pour initialiser la langue et fournir une fonction pour la changer :

 const [langue, setLangue] = useState('fr');

function changerLangue() {
  setLangue(langue === 'fr' ? 'en' : 'fr');
}

Un bouton déclenche la fonction changerLangue lors d'un clic, modifiant ainsi la valeur du contexte et actualisant les composants qui en dépendent.

4. Rendu de l'Application

Le code crée un root et rend le composant App dans l'élément DOM avec l'id 'root' :

 const root = createRoot(document.getElementById('root'));
root.render(<App />);

Remarques supplémentaires

  • Organisation du code : La séparation entre le composant parent (App) qui gère l’état et le composant enfant (Salutation) qui consomme le contexte permet une gestion claire et modulable de l’état dans l'application.
  • Utilisation de fragments : Dans le composant Salutation, le retour utilise un fragment (<>...</>) pour envelopper le contenu sans ajouter d'élément supplémentaire dans le DOM.

En résumé, ce code démontre comment créer un contexte avec une valeur par défaut, fournir cette valeur aux composants enfants et permettre leur mise à jour dynamique via useContext et useState.

Code complet :

📋 Copier le code

import React, { createContext, useContext, useState } from 'react';
import { createRoot } from 'react-dom/client';

// Création du Contexte
const LangueContext = createContext('fr'); // Valeur par défaut : "fr"

// Composant Fils qui utilise le contexte
function Salutation() {
    const langue = useContext(LangueContext);

    return (
        <p>
            {langue === 'fr' ? 'Bonjour' : 'Hello'} !
        </p>
    );
}

// Composant Parent qui fournit le contexte
function App() {
    const [langue, setLangue] = useState('fr');

    function changerLangue() {
        setLangue(langue === 'fr' ? 'en' : 'fr');
    }

    return (
        <LangueContext.Provider value={langue}>
            <div>
                <h1>Gestion de Contexte avec useContext</h1>
                <Salutation />
                <button onClick={changerLangue}>Changer de langue</button>
            </div>
        </LangueContext.Provider>
    );
}

const root = createRoot(document.getElementById('root'));
root.render(<App />);
        

Explication détaillée ligne par ligne :

  1. const LangueContext = createContext('fr'); :
    • Cette ligne crée un contexte appelé LangueContext avec une valeur par défaut ('fr').
  2. function Salutation() { ... } :
    • Ce composant fils utilise useContext pour accéder à la valeur du contexte LangueContext.
    • Il affiche un message de salutation ("Bonjour" ou "Hello") en fonction de la langue sélectionnée.
  3. const langue = useContext(LangueContext); :
    • Cette ligne utilise useContext pour récupérer la valeur actuelle du contexte LangueContext.
    • langue représente la langue actuelle (par exemple, 'fr' ou 'en').
  4. <LangueContext.Provider value={langue}> :
    • LangueContext.Provider est utilisé pour fournir la valeur actuelle du contexte (langue) à tous les composants enfants.
    • value={langue} spécifie la valeur du contexte (par exemple, 'fr' ou 'en').
  5. function changerLangue() { ... } :
    • Cette fonction alterne entre les langues 'fr' et 'en'.
    • setLangue(langue === 'fr' ? 'en' : 'fr') met à jour l'état langue en inversant sa valeur actuelle.

Conclusion

Vous avez maintenant appris à utiliser le Hook `useContext` pour partager des données globales entre plusieurs composants React. En éliminant le props drilling, `useContext` simplifie considérablement la gestion de l'état global dans vos applications React.

Prochain chapitre : useRef