paint-brush
So vereinfachen Sie die Statusverwaltung mit der React.js Context API – Ein Tutorialvon@codebucks
669 Lesungen
669 Lesungen

So vereinfachen Sie die Statusverwaltung mit der React.js Context API – Ein Tutorial

von CodeBucks11m2024/08/02
Read on Terminal Reader

Zu lang; Lesen

Dieser Blog bietet eine umfassende Anleitung zur Statusverwaltung in React mithilfe der Context API. Er erklärt, wie Sie Prop Drilling vermeiden, die Leistung verbessern und die Context API effektiv implementieren. Mit praktischen Beispielen und Optimierungstipps ist er perfekt für Entwickler, die die Statusverwaltung in ihren React-Anwendungen optimieren möchten.
featured image - So vereinfachen Sie die Statusverwaltung mit der React.js Context API – Ein Tutorial
CodeBucks HackerNoon profile picture
0-item

Hallo👋🏻,


Dieser Artikel richtet sich speziell an Anfänger, die effektivere Methoden zur Verwaltung des Status zwischen mehreren Komponenten erlernen möchten. Er befasst sich auch mit dem häufigen Problem des Prop Drilling, das die Wartung und das Verständnis Ihres Codes erschweren kann. Beginnen wir mit der Frage, welche Art von Problem die Context-API löst.


Wenn Sie das Videoformat bevorzugen, finden Sie hier das Tutorial, das Sie auf meinem YouTube-Kanal ansehen können.👇🏻


Was ist Propellerbohren?

Sie wissen, dass Sie manchmal Daten von einer übergeordneten Komponente an eine untergeordnete Komponente weitergeben müssen und dabei Props durch eine Reihe von Komponenten dazwischen übergeben müssen? Das nennt man Prop Drilling und kann schnell unübersichtlich werden. Lassen Sie uns dies anhand eines Beispiels verdeutlichen.


Props Drilling in React.js

Stellen Sie sich vor, Sie haben, wie im Diagramm gezeigt, einige Daten in der App Komponente abgerufen, die sich an der Wurzel Ihrer Anwendung befindet. Wenn nun eine tief verschachtelte Komponente, beispielsweise die Grandchild Komponente, auf diese Daten zugreifen muss, würden Sie sie normalerweise als Props durch die Parent und Child Komponenten weiterreichen, bevor sie Grandchild erreichen. Dies kann unschön werden, wenn Ihre App wächst.


Hier ist eine weitere visuelle Darstellung:


Reactjs Props Drilling Beispiel

Im obigen Beispiel benötigt die Profile Benutzerdaten, aber diese Daten müssen zuerst durch die App und Navigation , obwohl diese Zwischenkomponenten die Daten selbst nicht verwenden. Wie können wir das also bereinigen? Hier kommt die Context API ins Spiel.


Stützenbohrungen:

  • Erhöht das erneute Rendern von Komponenten
  • Erhöht den Boilerplate-Code
  • Erstellt Komponentenabhängigkeiten
  • Verringert die Leistung

React Context-API

Mit der Context API in React.js können Sie Daten zwischen Komponenten weitergeben, ohne sie als Props durch jede Ebene des Komponentenbaums weitergeben zu müssen. Es funktioniert wie ein globales Statusverwaltungssystem, in dem Sie Ihren Status in einem Kontextobjekt definieren und dann überall im Komponentenbaum problemlos darauf zugreifen können. Lassen Sie uns dies anhand eines Beispiels verstehen.


React.js Kontext-API

Wie Sie im Diagramm sehen können, haben wir ein Kontextobjekt, das Daten speichert, auf die mehrere Komponenten zugreifen können. Diese Daten werden von APIs oder Diensten von Drittanbietern abgerufen. Bevor wir in einer Komponente auf diese Kontextdaten zugreifen können, müssen wir alle Komponenten, die diese Daten benötigen, in eine Kontextanbieterkomponente einbinden.


Wenn wir nur auf Daten in den Navigations- und Profilkomponenten zugreifen müssen, müssen wir die App-Komponente nicht umschließen. Sobald Sie die relevanten Komponenten mit dem ContextProvider umschlossen haben, können Sie direkt auf die Kontextdaten in jeder Komponente zugreifen, die sie verwendet. Keine Sorge, wenn Sie es noch nicht verstehen; lassen Sie uns in den Code eintauchen und ihn in Aktion sehen.


Wie verwende ich die Context-API?

Lassen Sie uns zunächst eine React-App mit Vite.js erstellen. Kopieren Sie einfach die folgenden Befehle, um das Projekt einzurichten.


 npm create vite@latest


  • Fügen Sie Ihren Projektnamen hinzu
  • Wählen Sie React
  • Wählen Sie Typescript aus den Optionen
 cd project_name // to change to project directory npm install npm run dev


Anschließend können Sie Ihren Entwicklungsserver http://localhost:5173 in Ihrem Browser öffnen.


Lassen Sie uns zunächst die erforderlichen Ordner erstellen. Hier ist die Ordnerstruktur unseres Projekts.

 src | components | context


Erstellen wir im Komponentenordner die Datei Profile.jsx und fügen den folgenden Code hinzu.

 import React from 'react' const Profile = () => { return ( <div>Profile</div> ) } export default Profile


Erstellen Sie eine weitere Komponente namens Navbar.jsx im Komponentenordner.

 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


Importieren wir diese <Navbar /> -Komponente in die Datei 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;


Grundsätzlich ist die Komponente <Profile /> das untergeordnete Element der Komponente <Navbar /> und <Navbar /> ist das untergeordnete Element der Komponente <App /> .

Hinzufügen der Context-API

Erstellen wir die Datei UserContext.jsx im context . Fügen Sie der Datei den folgenden Code hinzu.


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


  • Zuerst erstellen wir mit createContext ein leeres UserContext Objekt. Wir stellen sicher, dass wir es aus react importieren. Wir können dem Kontextobjekt Standardwerte hinzufügen, aber wir lassen es vorerst null.


  • Als nächstes erstellen wir UserProvider , der einen Provider mit UserContext zurückgibt, wie etwa UserContext.Provider . Er umschließt die untergeordneten Komponenten und im Wert können wir alles übergeben, was wir in den untergeordneten Komponenten verwenden möchten.


  • Im Moment verwenden wir die JSON-Placeholder-API, um die Benutzerdaten abzurufen. Der JSON-Placeholder stellt zu Testzwecken gefälschte API-Endpunkte bereit. Die Funktion fetchUserData akzeptiert id und verwendet diese ID, um die Benutzerdaten abzurufen. Dann speichern wir die Antwort im user .


  • Wir rufen die Funktion fetchUserData im useEffect auf, sodass beim Laden der Seite die Funktion aufgerufen wird und die Daten in user eingefügt werden.


Lassen Sie uns nun diesen Kontext in der Komponente <App /> verwenden. Umschließen Sie die Komponente <NavBar /> mit <UserProvider /> ; dasselbe wie im folgenden Code:

 <UserProvider> <Navbar /> </UserProvider>


Lassen Sie uns den user in der Komponente <Profile /> verwenden. Dazu verwenden wir useContext Hook. Dieser nimmt UserContext und stellt die Werte bereit, die wir im UserProvider übergeben haben, wie z. B. user und fetchUserData -Funktion. Denken Sie daran, dass wir die Komponente <Profile /> nicht umschließen müssen, da sie sich bereits in der Komponente <Navbar /> befindet, die bereits mit dem Provider umschlossen ist.


Öffnen Sie Profile.jsx und fügen Sie den folgenden Code hinzu.

 const { user } = useContext(UserContext); if (user) { return ( <span style={{ fontWeight: "bold", }} > {user.name} </span> ); } else { return <span>Login</span>; }


Hier verwenden wir den user aus dem UserContext . Wir zeigen den Benutzernamen an, wenn user vorhanden ist, andernfalls zeigen wir nur eine Anmeldenachricht an. Wenn Sie jetzt die Ausgabe sehen, sollte in der Navigationsleistenkomponente ein Benutzername vorhanden sein. Auf diese Weise können wir jeden Status direkt verwenden, der im Kontext einer beliebigen Komponente steht. Die Komponente, die diesen Status verwendet, sollte in <Provider /> eingeschlossen werden.


Sie können auch mehrere Kontexte verwenden. Sie müssen die Anbieterkomponenten lediglich in eine andere Anbieterkomponente einbinden, wie im folgenden Beispiel gezeigt.

 <ThemeProvider> <UserProvider> <Navbar /> </UserProvider> </ThemeProvider>


Im obigen Beispiel verwenden wir <ThemeProvider /> , das den Designstatus verwaltet.


Sie können sich das obige YouTube-Video ansehen, um das vollständige Beispiel der Verwendung mehrerer Kontextanbieter zu sehen.

Optimieren des erneuten Renderns in der React Context API

Es gibt ein Problem, das auftritt, wenn Sie die Context API in mehreren Komponenten verwenden. Immer wenn sich der Status oder Wert in der Context API ändert, werden alle Komponenten, die diesen bestimmten Kontext abonniert haben, neu gerendert, auch wenn nicht alle Komponenten den geänderten Status verwenden. Um dieses Problem des erneuten Renderings zu verstehen, erstellen wir eine <Counter /> Komponente, die Kontext zum Speichern und Anzeigen von Zählwerten verwendet.


Schauen Sie sich das folgende Beispiel an. Sie können eine Datei Counter.jsx im Komponentenordner erstellen und den folgenden Code einfügen.


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


Im obigen Code:

  • Zuerst erstellen wir ein CountContext Objekt mit createContext.


  • Im CountProvider, haben wir einen Status zum Speichern von Zählwerten. Wir senden count und die setCount Methode über value prop an die untergeordneten Komponenten.


  • Wir haben Komponenten separat erstellt, um zu sehen, wie oft einzelne Komponenten erneut gerendert werden.

    • <CountTitle /> : Diese Komponente zeigt nur den Titel an und verwendet keine Werte aus dem Kontext.

    • <CountDisplay /> : Diese Komponente zeigt Zählwerte an und verwendet count aus dem Kontext.

    • <CounterButton /> : Diese Komponente rendert sowohl die obige Komponente als auch eine Schaltfläche, die die Zählwerte mit setCount erhöht.


  • Am Ende kapseln wir die Komponente <CounterButton /> in die Komponente CountProvider ein, damit die anderen Komponenten auf die Zählwerte zugreifen können.


Wenn Sie nun den Code ausführen und auf die Schaltfläche Increase klicken, sehen Sie in den Protokollen, dass jede Komponente bei jeder Statusänderung neu gerendert wird. <CountTitle /> verwendet nicht einmal Zählwerte, wird aber neu gerendert. Dies geschieht, weil die übergeordnete Komponente von <CountTitle /> also <CounterButton /> den Wert von count verwendet und aktualisiert und deshalb neu gerendert wird.


Wie können wir dieses Verhalten optimieren? Die Antwort lautet memo . Mit dem React- memo können Sie das erneute Rendern einer Komponente überspringen, wenn ihre Eigenschaften unverändert bleiben. Fügen wir nach der Komponente <CountTitle /> die folgende Zeile hinzu.


 const MemoizedCountTitle = React.memo(CountTitle)


Ersetzen Sie nun in der Komponente <CounterButton /> , in der wir die Komponente <CountTitle /> rendern, <CountTitle /> durch <MemoizedCountTitle /> wie im folgenden Code:


 <> <MemoizedCountTitle /> <CountDisplay /> <button onClick={() => setCount(count + 1)}>Increase</button> </>


Wenn Sie jetzt die Anzahl erhöhen und die Protokolle überprüfen, sollten Sie feststellen können, dass die Komponente <CountTitle /> nicht mehr gerendert wird.

Redux vs. Context-API

Redux ist eine State-Management-Bibliothek für komplexes State-Management mit besser vorhersehbaren State-Übergängen. Die Context-API hingegen ist für einfaches State-Management und die Weitergabe von Daten durch den Komponentenbaum ohne Prop Drilling konzipiert. Also, wann soll man was wählen?


  • Verwenden Sie die React Context API für eine einfache, lokalisierte Statusverwaltung, wenn sich der Status nicht häufig ändert.


  • Verwenden Sie Redux für komplexe Anforderungen an die Statusverwaltung, insbesondere bei größeren Anwendungen, bei denen die Vorteile der strukturierten Statusverwaltung den zusätzlichen Einrichtungsaufwand überwiegen.


Es gibt außerdem noch eine weitere Bibliothek, die ebenfalls eine beliebte Option für die Statusverwaltung ist: React Recoil .


  • React Recoil ist eine Statusverwaltungsbibliothek für React, die die Einfachheit der Context API mit der Leistungsfähigkeit und Performance von Redux vereinen soll.


Wenn Sie mehr über React Recoil erfahren möchten, lassen Sie es mich in den Kommentaren wissen und ich werde basierend auf Ihrem Feedback ausführliche Tutorials zu diesem Thema erstellen.

Abschluss

Die Context API React.js bietet eine leistungsstarke und effiziente Möglichkeit, Zustände über mehrere Komponenten hinweg zu verwalten und löst damit effektiv das Problem des Prop Drilling. Durch die Verwendung der Context API können Sie Ihren Code vereinfachen, unnötige Neurendervorgänge reduzieren und die Gesamtleistung der Anwendung verbessern.


Während die Context API ideal für einfaches Statusmanagement ist, können komplexere Anwendungen von der Verwendung von Redux oder anderen Statusmanagement-Bibliotheken wie React Recoil profitieren. Wenn Sie wissen, wann und wie Sie diese Tools verwenden, können Sie besser wartbare und skalierbare React-Anwendungen erstellen.


Vielen Dank für das Lesen dieses Artikels. Ich hoffe, Sie fanden ihn hilfreich. Wenn Sie daran interessiert sind, React, Redux und Next.js zu lernen und Projekte damit zu erstellen, können Sie meinen YouTube-Kanal hier besuchen: CodeBucks


Hier sind meine anderen Artikel, die Sie vielleicht lesen möchten:

Besuchen Sie meinen persönlichen Blog: DevDreaming