• 12 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/23/24

Partagez vos données avec le Contexte et useContext

Découvrez le Contexte dans React

Dans la famille des hooks, je veux maintenant celui qui nous permet d’utiliser simplement le Contexte de React !

Mais d’ailleurs, React Context, c’est quoi ? 🤔

Contexte est un moyen de partager simplement les props entre les composants. Contexte est natif à React et ne nécessite pas d'installer quoi que ce soit de plus.

Si vous avez suivi le cours précédent, vous avez vu comment passer de simples props entre les composants parents et enfants, et comment utiliser les props pour faire remonter le state, au chapitre “Partagez votre state entre différents composants". Mais est-ce que vous imaginez ce que ça pourrait donner dans une application complexe, où pour passer une prop à un composant enfant, vous devez le faire passer par des dizaines de composants parents qui n’ont eux-mêmes pas besoin de cette prop ?

Pour qu’un composant enfant accède aux données, le composant parent le fait descendre à travers plusieurs composants.
Ça n'a pas l'air très efficace, n'est-ce pas ?

À l’inverse, Contexte nous permet de récupérer simplement nos datas sans avoir à tout passer manuellement. Pour cela, on englobe le composant parent le plus haut dans l’arborescence de composants avec ce qu’on appelle un Provider  . Tous les composants enfants pourront alors se connecter au Provider  (littéralement en anglais, le “fournisseur”) et ainsi accéder aux props, sans avoir à passer par tous les composants intermédiaires. On dit que les composants enfants sont les Consumers  (consommateurs).

Au lieu de devoir passer les données comme dans le schéma précédent, le composant enfant se branche au Provider qui englobe le composant parent.
Cette fois-ci, le composant se branche tout simplement au Provider pour accéder au Contexte !

L’idée de passer simplement nos datas entre les composants est au cœur de nombreuses questions, afin que le code soit le plus performant et lisible possible. Vous verrez plus particulièrement des interrogations sur la manière de gérer le state de manière compréhensible et performante. On parle alors de State Management. Vous en avez déjà entendu parler ?

Avant les hooks, l’utilisation du Contexte était plus laborieuse, mais réjouissez-vous : vous avez maintenant le hook useContext  . 😍

Tirez profit du Contexte et de useContext

Maintenant que nous avons vu ce qu’était un Contexte, utilisons-le dès maintenant dans notre application Shiny !

Mettez en place un Contexte

Quelles données mettre dans le Contexte ?

La documentation de React dit que "le Contexte est conçu pour partager des données qui peuvent être considérées comme globales", et cite en exemple des données sur l’utilisateur actuellement authentifié, le thème, la langue utilisée, etc.

Nous allons commencer en douceur avec le contexte pour créer un Dark Mode (mode nuit) pour notre application. Vous savez, ce thème de couleurs plutôt sombres qui permet de reposer ses yeux devant l’écran.

Pour cela, nous allons créer un Footer dans lequel on ajoute un bouton. Dans /components  , on crée donc un fichier Footer/index.jsx  au fonctionnement assez basique :

import styled from 'styled-components'
import colors from '../../utils/style/colors'
 
const FooterContainer = styled.footer`
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding-top: 60px;
`
 
const NightModeButton = styled.button`
    background-color: transparent;
    border: none;
    cursor: pointer;
    color: ${colors.secondary};
`
 
function Footer() {
    return (
        <FooterContainer>
            <NightModeButton>Changer de mode</NightModeButton>
        </FooterContainer>
    )
}
 
export default Footer

Ce bouton dans notre Footer permettra de déclencher le dark mode de l’application. C’est maintenant le moment de créer notre Provider de Contexte pour le thème. Pour cela, on va créer un dossier dédié au Contexte dans utils/context  . On crée un fichier index.jsx  .

On commence par importer  { createContext }   depuis react  , et initialiser notre Contexte pour le thème avec :

export const ThemeContext = createContext()

Et on utilise ensuite ThemeContext  :

export const ThemeProvider = ({ children }) => {
    const [theme, setTheme] = useState('light')
    const toggleTheme = () => {
        setTheme(theme === 'light' ? 'dark' : 'light')
    }
 
    return (
        <ThemeContext.Provider value={{ theme, toggleTheme }}>
            {children}
        </ThemeContext.Provider>
    )
}

On a bien créé un composant qui nous permet de wrapper notre composant parent avec notre Provider  de thème. Le state de theme  et sa fonction pour le modifier, setTheme  , sont passés dans les values  . Ainsi, tous les composants enfants qui se retrouvent englobés par le Provider  vont pouvoir accéder à theme  et setTheme  .

C'est le moment d'utiliser notre Provider  au plus haut niveau où les composants devront pouvoir accéder au Contexte. On va donc le mettre dans index.jsx  à la racine de /src  . On a donc maintenant :

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <ThemeProvider>
        <GlobalStyle />
        <Header />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/survey/:questionNumber" element={<Survey />} />
          <Route path="/results" element={<Results />} />
          <Route path="/freelances" element={<Freelances />} />
          <Route path="*" element={<Error />} />
        </Routes>
        <Footer />
      </ThemeProvider>
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);

Ça veut dire qu'on doit forcément mettre notre Provider  au niveau de notre router  ? 🤔

Eh bien… Pas nécessairement ! Comme son nom l'indique, le Contexte nous sert à "contextualiser" nos datas. Certaines parties de l'application ont besoin d'être au courant d'une partie du state, alors qu'il n'y en a pas du tout besoin ailleurs. À vous de voir quelle utilisation est la plus adaptée.

Accédez à vos données avec useContext

Mais du coup, c’est quoi useContext  ?

useContext  est un hook qui permet de se “brancher” depuis un composant enfant qui a été wrappé par un Provider  , et donc d’accéder simplement au state partagé.

Mettons-le en pratique dès maintenant.

On va d’abord utiliser le theme  pour effectuer une modification très visible : modifier le background-color  de toute notre application.

Auparavant, on avait notre GlobalStyle  dans notre fichier index.jsx  à la racine de /src  , mais on va le déplacer dans un fichier à part dans /utils/style/GlobalStyle.jsx  . On va également modifier GlobalStyle en composant fonction qui va nous permettre d'y utiliser des hooks (alors qu'avant c'était un simple styled component). On a donc :

function GlobalStyle() {
    return <StyledGlobalStyle />
}

Puis on importe ThemeContext  et useContext  avec :

import { useContext } from 'react'
import { ThemeContext } from '../context/ThemeProvider'

Ce qui nous permet de récupérer le thème :

function GlobalStyle() {
    const { theme } = useContext(ThemeContext)

    return <StyledGlobalStyle isDarkMode={theme === 'dark'} />
}

... et donc de passer une prop isDarkMode en fonction du thème activé.

Dans notre Style  , on l’utilise ainsi :

const StyledGlobalStyle = createGlobalStyle`
    * {
        font-family: 'Trebuchet MS', Helvetica, sans-serif;
    }
 
    body {
        /* Ici cette syntaxe revient au même que
        background-color: ${({ props }) =>
        props.isDarkMode ? '#2F2E41' : 'white'};
        */
        background-color: ${({ isDarkMode }) => (isDarkMode ? 'black' : 'white')};
        margin: 0;  
    }
`

Et c’est parti pour la dernière pièce de notre puzzle : l’implémentation du bouton permettant de changer de mode. ☀️/🌙

On retourne donc dans notre Footer/index.jsx  . De la même manière que ce qu’on a fait juste avant, on importe ThemeContext  et useContext  .

Et on récupère notre action toggleTheme  et theme  avec :

const { toggleTheme, theme } = useContext(ThemeContext)

… qu’on peut utiliser juste en dessous :

function Footer() {
    const { toggleTheme, theme } = useContext(ThemeContext)
    return (
        <FooterContainer>
        <NightModeButton onClick={() => toggleTheme()}>
            Changer de mode : {theme === 'light' ? '☀️' : '🌙'}
        </NightModeButton>
        </FooterContainer>
    )
}

Et si on teste………

Ma-gni-fique ! 🤩

La couleur du background change bien au clic sur le bouton
La couleur du background change bien au clic sur le bouton

Bravo à vous : vous venez de créer un Contexte et vous l’avez utilisé avec useContext  pour créer un dark mode dans votre application. 🎉

Comme je vous le disais, vous êtes un chanceux : avant les hooks, le Contexte était plus compliqué à mettre en œuvre. Je vous fais une démonstration juste en dessous de comment ça se passait. 👇

Exercez-vous

Vous allez maintenant mettre ça en pratique. Pour cet exercice, vous devez utiliser le Contexte pour récupérer les résultats du questionnaire entre les pages.

Vous pouvez commencer l'exercice sur la branche P2C2-begin . Dans context/index.jsx  , vous trouverez un SurveyProvider  prêt à être utilisé.

Dans  /Survey/index.jsx  , vous trouverez la base de code pour stocker les réponses de l'utilisateur dans le Contexte, ainsi que des boutons permettant de répondre.

Comme dans le premier cours, on utilise encore une fois le spread operator pour stocker notre objet : vous souvenez-vous de l'immutabilité du state au chapitre “Partagez votre state entre différents composants” ? Pour cet exercice, vous allez devoir :

  • Utiliser votre SurveyProvider dans src/index.jsx  .

  • Sauvegarder les résultats dans votre state depuis pages/Survey/index.jsx  .

  • Récupérer les résultats dans /pages/results.jsx  avec useContext  , et les afficher dans un simple console.log()  .

Sinon, vous trouverez tout le code de la solution sur la branche P2C2-solution .

En résumé

  • Le Contexte est une fonctionnalité de React permettant de partager le state entre plusieurs composants parents et enfants, à l'aide d'un Provider.

  • useContext  est un hook permettant de se "brancher" très simplement au Contexte, et donc d'accéder au State partagé.

  • L'utilisation du Contexte est une des méthodes de State Management, qui peut se cumuler avec d'autres méthodes, telles que l'utilisation de Redux.

Alors, comment ça s'est passé pour vous, l'utilisation du Contexte dans votre application avec le hook useContext  ?

Dans le prochain chapitre, nous continuerons notre exploration des hooks avec la création de custom hooks (on pourrait dire en français des "hooks personnalisés"). Nous allons même créer notre propre hook useFetch  pour appeler une API. La classe, n'est-ce pas ? 😎

Example of certificate of achievement
Example of certificate of achievement