Comprendre React Context en faisant un Dark mode
Ahmed Bouras
Posted on April 1, 2023
Dans ce tutoriel nous allons voir ensemble ce qu'est React Context et finir cette explication par un petit dark mode pour la mise en pratique.
Déjà, c'est quoi React Context ?
React Context (ou l'API de Context pour les plus intimes) va nous permettre de rendre disponible des données et/ou des fonctions, dans toute notre application.
Sans React Context, il est possible de le faire en passant par les props d'un parent à son enfant. Cependant, imaginez que vous ayez une architecture où vous avez un parent, qui à un enfant, qui à lui même un enfant, qui à lui même un enfant, etc.
Il serait fastidieux de mettre cela en place.
On appelle ça le prop drilling.
Context existe donc pour éviter le prop drilling.
Pour faire une métaphore, imaginez une famille dans une maison où l'on a le père, le fils, le petit-fils et l'arrière petit-fils.
Avec le prop drilling :
Le père souhaite donner les clés de la voiture familial à son arrière petit-fils. Pour cela, il doit donner les clés à son fils, qui va devoir les donner à son petit-fils, qui les donnera enfin à son arrière petit-fils.
Avec Context :
Le père pose les clés de la voiture dans le salon et celui qui à besoin des clés n'aura qu'a les récupérer. Les clés sont disponible pour tout le monde, sans passer par un intermédiaire.
Mais n'oublions pas les bonnes manières… Il faudra les demander, avant de les prendre 😉
Maintenant que nous avons vu la théorie, faisons un peu de pratique avec notre dark mode.
Il y aura 3 étapes principales :
- Créer le context
- Englober notre app dans le context créé
- Récupérer les données/fonctions de notre context
Juste pour le côté pratique, je vais tout mettre dans le dossier src
, et configurer le css dans un seul endroit. Ne gardez que les fichiers suivants : index.js
| index.css
| App.js
/* index.css */
*, ::before, ::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.app {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100vw;
height: 100vh;
}
.dark-theme {
background-color: #1B2430;
color: #F1F1F1;
}
.content {
width: 80%;
}
Créons un peu de contenu pour nous permettre de voir le changement qui va s'opérer avec le dark mode ainsi que le bouton qui vas nous permettre de switcher avec ce mode.
// ToggleButton.js
export default function ToggleButton() {
return <button>Toggle</button>
}
// Content.js
import ToggleButton from "./ToggleButton";
export default function Content() {
return (
<div className="content">
<h1>Hello world!</h1>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Voluptates id ratione voluptatibus iusto unde soluta
dicta cum nam, rerum sit labore at et ducimus nobis
expedita molestiae commodi nostrum eius voluptatem
reiciendis repellat accusamus placeat eveniet rem.
Consequuntur, ducimus dolorum. Sunt deserunt optio itaque
maxime eligendi temporibus magnam pariatur inventore.</p>
<ToggleButton />
</div>
)
}
// App.js
import Content from "./Content";
export default function App() {
return (
<div className="app">
<Content />
</div>
)
}
Maintenant que nous avons notre base, passons à ce qui nous intéresse vraiment et créons le fichier qui va fournir notre context : DarkModeProvider.js
.
1. Créer le context
Pour créer un context, rien de plus simple, il suffit d'utiliser la commande suivante :
export const DarkModeContext = createContext();
🔴 Attention ! Cette commande doit se trouver en dehors de vos composants. Notre fichier ressemble maintenant à cela pour le moment :
// DarkModeProvider.js
import { createContext } from "react"
export const DarkModeContext = createContext();
// début du composant
export default function DarkModeProvider() {
return (
<div>
</div>
)
}
// fin du composant
Pour la suite, nous allons créer une variable darkMode
qui aura pour valeur true
ou false
afin de savoir si le dark mode est activé. À cela, nous allons ajouter une fonction qui nous permettra permettra de switcher entre ces deux valeurs.
Ça tombe bien, il y a un Hook que nous allons utiliser pour cette tâche et c'est useState
.
import { createContext, useState } from "react"
export const DarkModeContext = createContext();
export default function DarkModeProvider() {
const [darkMode, setDarkMode] = useState(false);
function toggleDarkMode() {
setDarkMode(!darkMode);
}
return (
<div>
</div>
)
}
On initialise darkMode à false car initialement notre site sera en clair (couleur par défaut) :
false -> clair
true -> sombre
Puis la fonction toggleDarkMode()
permettra à chaque clique sur notre bouton, d'inverser les couleurs, c'est à dire de faire passer false
à sa valeur inverse : true
et ainsi de suite.
D'ailleurs, comment je fais pour transmettre cette fonction à mon bouton ToggleButton
?
2. Englober notre app dans le context créé
Il y a deux étapes pour "englober" notre app de notre context. On peut dire aussi que l'on fournis un context à notre app.
La première est d'englober notre composant App
par le composant DarkModeProvider
:
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import DarkModeProvider from "./DarkModeProvider";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<DarkModeProvider>
<App />
</DarkModeProvider>
</React.StrictMode>
);
// DarkModeProvider.js
import { createContext, useState } from "react"
export const DarkModeContext = createContext();
export default function DarkModeProvider({ children }) {
const [darkMode, setDarkMode] = useState(false);
function toggleDarkMode() {
setDarkMode(!darkMode);
}
return (
<DarkModeContext.Provider>
{children}
</DarkModeContext.Provider>
)
}
Ici, children
correspond à notre composant App
.
Autre petite étape avant de passer à la suite. On a rendu notre context disponible, c'est bien... Mais comment Context sait qu'il doit mettre telle ou telle donnée à disposition ?
Il faut les ajouter en tant que valeur comme ceci :
// DarkModeProvider.js
return (
<DarkModeContext.Provider
value={ {darkMode, toggleDarkMode} }>
{children}
</DarkModeContext.Provider>
)
}
On ajoute donc un objet avec ce que l'on souhaite rendre disponible.
3. Récupérer les données/fonctions de notre context
Est-ce que vous vous rappelez de ce que je vous ai dit plus haut ? Lorsque l'on souhaite obtenir quelque chose, on le demande gentiment. Ça fait partie des bonnes manières.
Pour obtenir ce que l'on souhaite, nous allons utiliser le Hook useContext. Il va nous permettre d'utiliser ce que Context à rendu disponible.
Avec cette ligne et grâce au destructuring, nous nous permettons de récupérer notre donnée et notre fonction renduent disponible par notre Context :
const {darkMode, toggleDarkMode} = useContext(DarkModeContext);
Maintenant que nous avons accès à notre fonction, nous allons l'ajouter et l'exécuter lorsque le bouton sera cliqué et pour vous montrer que cela fonctionne, nous allons loguer la valeur de darkMode
.
Votre code devrait ressembler à ceci :
import { useContext } from "react"
import { DarkModeContext } from "./DarkModeProvider"
export default function ToggleButton() {
const {darkMode, toggleDarkMode} = useContext(DarkModeContext);
console.log(darkMode);
return <button onClick={toggleDarkMode}>Toggle</button>
}
Maintenant, ouvrez la console et cliquez sur sur le bouton et vous verrez la valeur de darkMode
passer de false
à true
et ainsi de suite.
Super ! On a terminé toutes les étapes pour apprendre à utiliser les propriétés transmises par Context.
De ce fait, voici le code qui nous permet d'ajouter la classe dark-theme pour notre app :
import { useContext } from "react";
import Content from "./Content";
import { DarkModeContext } from "./DarkModeProvider";
export default function App() {
const {darkMode} = useContext(DarkModeContext);
return (
<div className={`app ${darkMode && 'dark-theme'}`}>
<Content />
</div>
)
}
On récupère la valeur de darkMode
et si elle est true
, alors la classe sera ajouté.
Conclusion
Context nous permets de rendre disponible nos données/fonctions beaucoup plus facilement. On utilise Context généralement pour des actions occasionnels (changement de thème, changement de la langue du site, …).
Je vous invite maintenant à lire la documentation officielle de React sur Context et useContext pour parfaire vos connaissances et réaliser les exemples qu'ils proposent.
Sayonara !
Posted on April 1, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.