ReactJS - Higher-Order Components: A Beginner's Guide
Hallo zusammen, zukünftige React-Zauberer! Heute begeben wir uns auf eine aufregende Reise in die Welt der Higher-Order Components (HOCs) in ReactJS. Keine Sorge, wenn ihr mới im Programmieren seid – ich werde dein freundlicher Guide sein, und wir werden dies Schritt für Schritt durchgehen. Am Ende dieses Tutorials wirst du HOCs wie ein Profi erstellen können!
Was sind Higher-Order Components?
Bevor wir eintauchen, lassen Sie uns verstehen, was Higher-Order Components sind. Stell dir vor, du bist in einem Burgerladen. Du bestellst einen normalen Burger, aber dann entscheidest du dich, Käse, Salat und Bacon hinzuzufügen. Der Prozess des Hinzufügens dieser Extras zu deinem Burger ist ähnlich zu dem, was HOCs in React tun!
In React-Begriffen ist eine Higher-Order Component eine Funktion, die ein Komponente nimmt und eine neue Komponente mit einiger zusätzlicher Funktionalität zurückgibt. Es ist wie eine spezielle Soße, die deine vorhandenen Komponenten verbessert, ohne ihre Hauptzutaten zu ändern.
Hier ist eine einfache Analogie:
// Das ist wie unser normaler Burger
const PlainBurger = () => <div>?</div>;
// Das ist unsere HOC, wie das Hinzufügen von Belägen
const addCheese = (Burger) => {
return () => (
<div>
<Burger />
<span>?</span>
</div>
);
};
// Das ist unser mit Käse verbesserte Burger!
const CheeseBurger = addCheese(PlainBurger);
In diesem Beispiel ist addCheese
unsere Higher-Order Component. Sie nimmt unseren PlainBurger
und gibt eine neue Komponente mit Käse zurück!
Wie man Higher-Order Components verwendet
Nun, da wir das Konzept verstehen, sehen wir uns an, wie wir HOCs in einer praktischeren Situation verwenden können. Angenommen, wir haben mehrere Komponenten, die Daten von einer API abrufen müssen. Anstatt die gleiche Abruflogik in jedem Komponenten zu schreiben, können wir eine HOC erstellen, die dies für uns erledigt.
Hier ist, wie wir das tun könnten:
import React, { useState, useEffect } from 'react';
// Das ist unsere HOC
function withDataFetching(WrappedComponent, dataSource) {
return function(props) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(dataSource)
.then(response => response.json())
.then(result => {
setData(result);
setLoading(false);
})
.catch(e => {
setError(e);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <WrappedComponent data={data} {...props} />;
}
}
// Das ist eine einfache Komponente, die die abgerufenen Daten empfangen wird
function UserList({ data }) {
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
// Wir verwenden unsere HOC, um eine neue Komponente mit Datenabrufkapazitäten zu erstellen
const UserListWithData = withDataFetching(UserList, 'https://api.example.com/users');
// Jetzt können wir UserListWithData in unserer App verwenden!
function App() {
return (
<div>
<h1>User List</h1>
<UserListWithData />
</div>
);
}
Lassen wir das auseinanderbrechen:
-
Wir definieren unsere HOC
withDataFetching
. Sie nimmt zwei Parameter: die Komponente, die wir umwickeln möchten (WrappedComponent
) und die URL, von der wir Daten abrufen (dataSource
). -
Innerhalb von
withDataFetching
erstellen und geben wir eine neue funktionale Komponente zurück. Diese Komponente verwendet React Hooks, um den Zustand und Nebenwirkungen zu verwalten. -
Wir verwenden
useState
, um unserendata
,loading
underror
Zustände zu verwalten. -
Wir verwenden
useEffect
, um Daten zuAbrufen, wenn die Komponente montiert wird. Sobald die Daten abgerufen sind, aktualisieren wir unseren Zustand entsprechend. -
Abhängig vom Zustand zeigen wir entweder eine Ladebotschaft, eine Fehlermeldung oder rendern die
WrappedComponent
mit den abgerufenen Daten. -
Wir erstellen eine einfache
UserList
Komponente, die erwartet, Daten als Prop zu empfangen und sie anzuzeigen. -
Wir verwenden unsere HOC, um eine neue Komponente
UserListWithData
zu erstellen, die Datenabruferfähigkeiten hat. -
Schließlich verwenden wir
UserListWithData
in unsererApp
Komponente.
Anwendung von HOC Komponenten
Nun, da wir gesehen haben, wie man HOCs erstellt und verwendet, schauen wir uns einige häufige Anwendungsfälle und Best Practices an.
Authentifizierungs-HOC
Eine häufige Verwendung von HOCs ist die Handhabung der Authentifizierung. Hier ist ein Beispiel:
function withAuth(WrappedComponent) {
return function(props) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
// Überprüfen, ob der Benutzer authentifiziert ist
const token = localStorage.getItem('token');
setIsAuthenticated(!!token);
}, []);
if (!isAuthenticated) {
return <Redirect to="/login" />;
}
return <WrappedComponent {...props} />;
}
}
// Verwendung
const ProtectedComponent = withAuth(SensitiveDataComponent);
Diese HOC überprüft, ob der Benutzer authentifiziert ist, bevor die umwickelte Komponente gerendert wird. Wenn nicht, wird auf die Login-Seite weitergeleitet.
Protokollierungs-HOC
Eine andere nützliche Anwendung ist das Hinzufügen von Protokollierung zu Komponenten:
function withLogging(WrappedComponent) {
return function(props) {
useEffect(() => {
console.log(`Component ${WrappedComponent.name} mounted`);
return () => console.log(`Component ${WrappedComponent.name} unmounted`);
}, []);
return <WrappedComponent {...props} />;
}
}
// Verwendung
const LoggedComponent = withLogging(MyComponent);
Diese HOC protokolliert, wenn die Komponente montiert und demontiert wird, was sehr nützlich für das Debugging sein kann.
Best Practices und Überlegungen
Beim Arbeiten mit HOCs sollten Sie diese Tipps im Hinterkopf behalten:
- Verändere nicht die Originalkomponente: Verwandle immer die Originalkomponente mit der neuen Funktionalität.
- Lege无关的属性 durch: Stelle sicher, dass du alle无关的属性 durchgibst, die nicht spezifisch für die HOC sind.
- Maximiere die Komposition: HOCs sollten in der Lage sein, mit anderen HOCs kombiniert zu werden.
-
Verwende das Display Name für einfaches Debugging: Verwende
React.displayName
, um deiner HOC einen klaren Namen in React DevTools zu geben.
Hier ist eine Tabelle, die einige häufige HOC-Muster zusammenfasst:
Muster | Beschreibung | Beispielanwendung |
---|---|---|
Props Proxy | Manipulation von Props | Hinzufügen/Ändern von Props |
Inheritance Inversion | Erweiterung des Komponenten-Lebenszyklus | Hinzufügen von Protokollierung zu Lebenszyklusmethoden |
Render Highjacking | Steuerung der Render-Ausgabe | Bedingtes Rendern |
State Abstraction | Verwaltung und Bereitstellung von Zustand | Abrufen und Bereitstellen von Daten |
Denken Sie daran, Higher-Order Components sind ein leistungsstarkes Werkzeug in Ihrem React-Werkzeugkasten, aber sie sind nicht immer die beste Lösung. Mit der Einführung von Hooks in React können einige Anwendungsfälle für HOCs eleganter mit benutzerdefinierten Hooks gelöst werden. Überlegen Sie immer die spezifischen Bedürfnisse Ihrer Anwendung, wenn Sie entscheiden, ob Sie HOCs, Hooks oder andere Muster verwenden möchten.
Und da hast du es, Leute! Du hast gerade deine ersten Schritte in die Welt der Higher-Order Components in React gemacht. Übe diese Konzepte, experimentiere mit deinen eigenen HOCs und bald wirst du Komponenten wie ein Maestro eine Orchester leiten. Frohes Coden!
Credits: Image by storyset