Bonjour👋🏻,
Cet article est spécialement créé pour les débutants désireux d'apprendre des méthodes plus efficaces pour gérer l'état entre plusieurs composants. Il vise également à résoudre le problème courant du perçage d'accessoires, qui peut rendre votre code plus difficile à maintenir et à comprendre. Commençons par quel type de problème l'API de contexte résout.
Si vous préférez le format vidéo, alors voici le tutoriel que vous pouvez visionner sur ma chaîne YouTube.👇🏻
Vous savez que parfois vous devez transmettre des données d'un composant parent à un composant enfant, et vous finissez par transmettre des accessoires à travers un tas de composants intermédiaires ? C'est ce qu'on appelle le forage d'hélices , et cela peut vite devenir compliqué. Passons en revue un exemple pour clarifier cela.
Comme le montre le diagramme, imaginez que vous avez récupéré des données dans le composant App
, qui se trouve à la racine de votre application. Désormais, si un composant profondément imbriqué, par exemple le composant Grandchild
, a besoin d'accéder à ces données, vous le transmettez généralement via les composants Parent
et Child
en tant qu'accessoires avant qu'ils n'atteignent Grandchild
. Cela peut devenir moche à mesure que votre application se développe.
Voici une autre représentation visuelle :
Dans l'exemple ci-dessus, le composant Profile
a besoin de données utilisateur, mais ces données doivent d'abord transiter par les composants App
et Navigation
, même si ces composants intermédiaires n'utilisent pas les données eux-mêmes. Alors, comment pouvons-nous nettoyer cela ? C'est là que l'API Context s'avère utile.
Forage d'accessoires :
L'API contextuelle dans React.js vous permet de transmettre des données entre composants sans avoir besoin de les transmettre en tant qu'accessoires à chaque niveau de l'arborescence des composants. Il fonctionne comme un système de gestion d'état global dans lequel vous définissez votre état dans un objet contextuel, puis vous pouvez facilement y accéder n'importe où dans l'arborescence des composants. Comprenons cela avec un exemple.
Comme vous pouvez le voir sur le diagramme, nous avons un objet contextuel qui stocke les données auxquelles plusieurs composants peuvent accéder. Ces données sont récupérées à partir d'API ou de services tiers. Avant d'accéder à ces données de contexte dans n'importe quel composant, nous devons envelopper tous les composants qui nécessitent ces données dans un composant fournisseur de contexte.
Si nous avons uniquement besoin d'accéder aux données des composants de navigation et de profil, nous n'avons pas besoin de terminer le composant d'application. Une fois que vous avez encapsulé les composants pertinents avec ContextProvider
, vous pouvez accéder directement aux données contextuelles dans n'importe quel composant qui les consomme. Ne vous inquiétez pas si vous ne le comprenez toujours pas ; Plongeons dans le code et voyons-le en action.
Tout d'abord, créons une application React à l'aide de Vite.js . Copiez simplement les commandes suivantes pour configurer le projet.
npm create vite@latest
cd project_name // to change to project directory npm install npm run dev
Ensuite, vous pouvez ouvrir votre serveur de développement http://localhost:5173
dans votre navigateur.
Commençons par créer les dossiers requis. Voici la structure des dossiers de notre projet.
src | components | context
Dans le dossier des composants, créons le fichier Profile.jsx
et ajoutons le code suivant.
import React from 'react' const Profile = () => { return ( <div>Profile</div> ) } export default Profile
Créez un composant supplémentaire appelé Navbar.jsx
dans le dossier des composants.
import Profile from './Profile' const Navbar = () => { return ( <nav style={{ display: "flex", justifyContent: "space-between", alignItems: "center", width: "90%", height: "10vh", backgroundColor: theme === "light" ? "#fff" : "#1b1b1b", color: theme === "light" ? "#1b1b1b" : "#fff", border: "1px solid #fff", borderRadius: "5px", padding: "0 20px", marginTop: "40px", }}> <h1>LOGO</h1> <Profile /> </nav> ) } export default Navbar
Importons ce composant <Navbar />
dans le fichier App.jsx
.
import Navbar from "./components/Navbar"; function App() { return ( <main style={{ display: "flex", flexDirection: "column", justifyContent: "start", alignItems: "center", height: "100vh", width: "100vw", }} > <Navbar /> </main> ); } export default App;
Donc, fondamentalement, le composant <Profile />
est l'enfant de <Navbar />
et <Navbar />
est l'enfant du composant <App />
.
Créons le fichier UserContext.jsx
dans le dossier context
. Ajoutez le code suivant au fichier.
import { createContext, useEffect, useState } from "react"; export const UserContext = createContext(); export const UserProvider = ({ children }) => { const [user, setUser] = useState(null); const fetchUserData = async (id) => { const response = await fetch( `https://jsonplaceholder.typicode.com/users/${id}` ).then((response) => response.json()); console.log(response); setUser(response); }; useEffect(() => { fetchUserData(1); }, []); return ( <UserContext.Provider value={{ user, fetchUserData }} > {children} </UserContext.Provider> ); };
UserContext
vide en utilisant createContext
. Nous veillons à l'importer depuis react
. Nous pouvons ajouter des valeurs par défaut à l'intérieur de l'objet contextuel, mais nous le gardons nul pour l'instant.
UserProvider
, qui renvoie un fournisseur utilisant UserContext
, comme UserContext.Provider
. Il entoure les composants enfants et, dans la valeur, nous pouvons transmettre tout ce que nous voulons utiliser dans les composants enfants.
fetchUserData
accepte id
et utilise cet identifiant pour récupérer les données utilisateur. Ensuite, nous stockons la réponse dans l'état user
.
fetchUserData
dans useEffect
donc lors du chargement de la page, elle appelle la fonction et injecte les données dans l'état user
.
Utilisons maintenant ce contexte dans le composant <App />
. Enveloppez le composant <NavBar />
à l'aide du <UserProvider />
; le même que le code suivant :
<UserProvider> <Navbar /> </UserProvider>
Utilisons l'état user
dans le composant <Profile />
. Pour cela, nous utiliserons le hook useContext
. Cela prend UserContext
et fournit les valeurs que nous avons transmises dans UserProvider
telles que l'état user
et la fonction fetchUserData
. N'oubliez pas que nous n'avons pas besoin d'encapsuler le composant <Profile />
puisqu'il se trouve déjà dans le composant <Navbar />
qui est déjà encapsulé avec le fournisseur.
Ouvrez le Profile.jsx
et ajoutez le code suivant.
const { user } = useContext(UserContext); if (user) { return ( <span style={{ fontWeight: "bold", }} > {user.name} </span> ); } else { return <span>Login</span>; }
Ici, nous utilisons l'état user
du UserContext
. Nous afficherons le nom d'utilisateur s'il y a user
, sinon nous afficherons juste un message de connexion. Maintenant, si vous voyez le résultat, il devrait y avoir un nom d'utilisateur dans le composant de la barre de navigation. C'est ainsi que nous pouvons utiliser directement n'importe quel état dans le contexte de n'importe quel composant. Le composant qui utilise cet état doit être encapsulé dans <Provider />
.
Vous pouvez également utiliser plusieurs contextes. Il vous suffit d'envelopper les composants du fournisseur dans un autre composant du fournisseur, comme indiqué dans l'exemple suivant.
<ThemeProvider> <UserProvider> <Navbar /> </UserProvider> </ThemeProvider>
Dans l'exemple ci-dessus, nous utilisons <ThemeProvider />
qui gère l'état du thème.
Vous pouvez regarder la vidéo YouTube ci-dessus pour voir l'exemple complet d'utilisation de plusieurs fournisseurs de contexte.
Un problème se produit lorsque vous utilisez l'API Context dans plusieurs composants. Chaque fois que l'état ou la valeur change dans l'API de contexte, elle restitue tous les composants abonnés à ce contexte particulier, même si tous les composants n'utilisent pas l'état modifié. Pour comprendre ce problème de nouveau rendu, créons un composant <Counter />
qui utilise le contexte pour stocker et afficher les valeurs de comptage.
Consultez l’exemple suivant. Vous pouvez créer un fichier Counter.jsx
dans le dossier des composants et coller le code suivant.
import { createContext, memo, useContext, useState } from "react"; const CountContext = createContext(); const CountProvider = ({ children }) => { const [count, setCount] = useState(0); return ( <CountContext.Provider value={{ count, setCount }}> {children} </CountContext.Provider> ); }; function CountTitle() { console.log("This is Count Title component"); return <h1>Counter Title</h1>; } function CountDisplay() { console.log("This is CountDisplay component"); const { count } = useContext(CountContext); return <div>Count: {count}</div>; } function CounterButton() { console.log("This is CounterButton component"); const { count, setCount } = useContext(CountContext); return ( <> <CountTitle /> <CountDisplay /> <button onClick={() => setCount(count + 1)}>Increase</button> </> ); } export default function Counter() { return ( <CountProvider> <CounterButton /> </CountProvider> ); }
Dans le code ci-dessus :
CountContext
à l’aide createContext.
CountProvider,
nous avons un état pour stocker les valeurs de comptage. Nous envoyons count
et la méthode setCount
aux composants enfants via value prop.
Nous avons créé des composants séparément pour voir combien de fois les composants individuels sont restitués.
<CountTitle />
: Ce composant affiche uniquement le titre et n'utilise même aucune valeur du contexte.
<CountDisplay />
: ce composant affiche les valeurs de comptage et utilise l'état count
du contexte.
<CounterButton />
: ce composant restitue à la fois le composant ci-dessus et un bouton qui augmente les valeurs de comptage à l'aide setCount
.
À la fin, nous encapsulons le composant <CounterButton />
dans le composant CountProvider
afin que les autres composants puissent accéder aux valeurs de comptage.
Maintenant, si vous exécutez le code et cliquez sur le bouton Increase
, vous verrez dans les journaux que chaque composant est restitué à chaque fois que l'état change. Le <CountTitle />
n'utilise même pas de valeurs de comptage, mais il est en cours de rendu. Cela se produit parce que le composant parent de <CountTitle />
qui est <CounterButton />
utilise et met à jour la valeur de count et c'est pourquoi il est restitué.
Comment pouvons-nous optimiser ce comportement ? La réponse est memo
. Le memo
React vous permet d'éviter de restituer un composant lorsque ses accessoires sont inchangés. Après le composant <CountTitle />
, ajoutons la ligne suivante.
const MemoizedCountTitle = React.memo(CountTitle)
Maintenant, dans le composant <CounterButton />
, où nous restituons le composant <CountTitle />
, remplacez le <CountTitle />
par <MemoizedCountTitle />
comme dans le code suivant :
<> <MemoizedCountTitle /> <CountDisplay /> <button onClick={() => setCount(count + 1)}>Increase</button> </>
Maintenant, si vous augmentez le nombre et vérifiez les journaux, vous devriez pouvoir voir qu'il ne restitue plus le composant <CountTitle />
.
Redux
est une bibliothèque de gestion d'état pour la gestion d'état complexe avec des transitions d'état plus prévisibles. Alors que l'API Context est conçue pour une gestion simple de l'état et la transmission de données via l'arborescence des composants sans perçage d'accessoires. Alors, quand choisir lequel ?
Il existe également une autre bibliothèque, qui constitue également une option populaire pour la gestion de l'État. Le recul de réaction .
Si vous souhaitez en savoir plus sur React Recoil , faites-le-moi savoir dans les commentaires et je créerai des didacticiels approfondis sur ce sujet en fonction de vos commentaires.
L'API contextuelle React.js
offre un moyen puissant et efficace de gérer les états de plusieurs composants, résolvant ainsi efficacement le problème du forage d'accessoires. En utilisant l'API Context, vous pouvez simplifier votre code, réduire les rendus inutiles et améliorer les performances globales des applications.
Bien que l'API Context soit idéale pour une gestion d'état simple, des applications plus complexes peuvent bénéficier de l'utilisation Redux
ou d'autres bibliothèques de gestion d'état comme React Recoil
. Comprendre quand et comment utiliser ces outils vous permettra de créer des applications React plus maintenables et évolutives.
Merci d'avoir lu cet article, j'espère que vous l'avez trouvé utile. Si vous souhaitez apprendre et créer des projets à l'aide de React, Redux et Next.js, vous pouvez visiter ma chaîne YouTube ici : CodeBucks
Voici mes autres articles que vous aimeriez peut-être lire :
Comment implémenter un défilement fluide dans Next.js avec Lenis et GSAP
Comment obtenir l'emplacement de l'utilisateur dans React.js
Top 10 des thèmes VS Code populaires que vous devriez essayer
Visitez mon blog personnel : DevDreaming