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!

ReactJS - Higher Order Components

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:

  1. 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).

  2. 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.

  3. Wir verwenden useState, um unseren data, loading und error Zustände zu verwalten.

  4. Wir verwenden useEffect, um Daten zuAbrufen, wenn die Komponente montiert wird. Sobald die Daten abgerufen sind, aktualisieren wir unseren Zustand entsprechend.

  5. Abhängig vom Zustand zeigen wir entweder eine Ladebotschaft, eine Fehlermeldung oder rendern die WrappedComponent mit den abgerufenen Daten.

  6. Wir erstellen eine einfache UserList Komponente, die erwartet, Daten als Prop zu empfangen und sie anzuzeigen.

  7. Wir verwenden unsere HOC, um eine neue Komponente UserListWithData zu erstellen, die Datenabruferfähigkeiten hat.

  8. Schließlich verwenden wir UserListWithData in unserer App 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:

  1. Verändere nicht die Originalkomponente: Verwandle immer die Originalkomponente mit der neuen Funktionalität.
  2. Lege无关的属性 durch: Stelle sicher, dass du alle无关的属性 durchgibst, die nicht spezifisch für die HOC sind.
  3. Maximiere die Komposition: HOCs sollten in der Lage sein, mit anderen HOCs kombiniert zu werden.
  4. 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