Verständnis von React-Custom-Hooks: Wiederverwendung von Logik ohne gemeinsamen Zustand
Erfahren Sie, was React-Custom-Hooks sind, wie sie logische Strukturen mit Zustand zwischen Komponenten extrahieren und teilen, sowie welche häufigen Fehler bei ihrer Erstellung vermieden werden sollten.
Einführung
Haben Sie schon einmal festgestellt, dass Sie im selben useState- und useEffect-Setup in drei verschiedenen Komponenten schreiben mussten, wobei nur die Variablennamen jedes Mal geändert wurden? Fast jeder React-Entwickler stößt irgendwann darauf. Der Code funktioniert zwar einwandfrei, doch dadurch wird identische Logik im gesamten Codebase dupliziert, und jede Kopie neigt dazu, im Laufe der Zeit durch unabhängige Anpassungen auseinanderzudriften.
Genau diese Situation wurde mit den benutzerdefinierten Hooks in React gelöst. Die React-Dokumentation zu diesem Thema erklärt, dass das Verhalten von Komponenten in eine eigene, wiederverwendbare Funktion ausgelagert werden kann, sodass verschiedene Teile einer Anwendung dasselbe statebasierte Verhalten teilen können, anstatt die zugrunde liegende Implementierung immer wieder zu kopieren. In diesem Teil des Artikels wird erläutert, was benutzerdefinierte Hooks eigentlich sind, wie sie sich in echtem Code verhalten sowie welche Vorteile und Fallstricke man kennen sollte, bevor man eigene erstellt.
Was sind React-Benutzerdefinierte Hooks?
Im Grunde genommen ist ein benutzerdefinierter Hook nichts anderes als eine JavaScript-Funktion, die einer strengen Namensregel folgt: Ihr Name muss mit use beginnen. Darin kann sie andere Hooks wie useState oder useEffect aufrufen und gibt die Werte oder Funktionen zurück, die das aufrufende Komponente benötigt. React selbst behandelt diese Funktion nicht auf besondere Weise während der Ausführung – das use-Präfix ist rein konventionell, doch es ist unerlässlich, da es React ermöglicht, die Regeln der Hooks korrekt durchzusetzen, und anderen Entwicklern sofort zeigt, wofür die Funktion dient.
Benutzerdefinierte Hooks gegenüber regulären Funktionen
Eine Standard-Utility-Funktion kann viel nützliche Arbeit leisten, doch sie darf keine anderen Hooks aufrufen, da sie außerhalb von Reacts Rendering-Mechanismus liegt. Ein benutzerdefinierter Hook hat diese Einschränkung nicht. Genau das ist sein Vorteil: Man kann statebasiertes Verhalten – wie das Verfolgen eines Ladezeichens, das Abhören von Browser-Events oder Ähnliches – in etwas Umsetzen, das wiederverwendbar ist und dennoch nahtlos in Reacts Komponentenlebenszyklus integriert werden kann.
Wie React Custom Hooks in der Praxis funktionieren
Ein konkretes Beispiel macht das weitaus schneller klar als jede abstrakte Erklärung.
Logik aus einer Komponente extrahieren
Stellen Sie sich drei unverwandte Komponenten vor, die jeweils überprüfen müssen, ob der Browser derzeit eine Netzwerkverbindung hat. Ohne einen gemeinsamen Hook müsste jede von ihnen ihre eigene useState- und useEffect-Einrichtung erstellen, um dies zu überwachen:
function StatusBadge() {
const [isOnline, setIsOnline] = useState(navigator.onLine);
useEffect(() => {
const goOnline = () => setIsOnline(true);
const goOffline = () => setIsOnline(false);
window.addEventListener('online', goOnline);
window.addEventListener('offline', goOffline);
return () => {
window.removeEventListener('online', goOnline);
window.removeEventListener('offline', goOffline);
};
}, []);
return <span>{isOnline ? 'Online' : 'Offline'}</span>;
}
Anstatt dessen kann man diese Logik in einen einzigen benutzerdefinierten Hook übertragen, und ab dann ruft einfach jedes Komponente, das den Status benötigt, diesen Hook auf:
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(navigator.onLine);
useEffect(() => {
const goOnline = () => setIsOnline(true);
const goOffline = () => setIsOnline(false);
window.addEventListener('online', goOnline);
window.addEventListener('offline', goOffline);
return () => {
window.removeEventListener('online', goOnline);
window.removeEventListener('offline', goOffline);
};
}, []);
return isOnline;
}
// Usage in any component:
function StatusBadge() {
const isOnline = useOnlineStatus();
return <span>{isOnline ? 'Online' : 'Offline'}</span>;
}
Keine der Komponenten muss sich mehr selbst um die Verbindung der Event-Listener kümmern – jede fragt einfach nach dem aktuellen Wert mit useOnlineStatus.
Teilen von Zustandslogik ohne Teilen des Zustands selbst
Das ist ein Detail, das viele Neueinsteiger überrascht: Ein benutzerdefinierter Hook teilt das Verhalten, nicht den Zustand selbst. Wenn zwei separate Komponenten jeweils useOnlineStatus aufrufen, erhält jede ihre eigene private Kopie dieses Zustands. Sie durchlaufen dieselbe Logik, doch die tatsächlichen Werte in jeder Komponente sind völlig unabhängig – es gibt keinen gemeinsamen oder verknüpften Zustand zwischen ihnen.
Hauptvorteile der Verwendung von React-Benutzerdefinierten Hooks
- Wiederverwendbarkeit über Komponenten hinweg: Sobald die Logik in einem Hook gespeichert ist, muss keine Komponente in der Anwendung eine einzige Zeile duplizieren, um sie zu verwenden, und es ist garantiert, dass sich das Verhalten überall dort, wo es genutzt wird, konsequent verhält.
- Klare, leichter lesbare Komponenten: Durch das Herausnehmen der Zustandslogik aus einer Komponente entfällt im verbleibenden Code größtenteils die Notwendigkeit, sich mit Zustumschaltungen auseinanderzusetzen, wodurch es für Neueinsteiger viel schneller möglich ist, den Code auf einen Blick zu verstehen.
- Einfachere getrennte Tests: Die extrahierte Logik kann vollständig unabhängig von jeder Komponente getestet werden, die sie verwendet, sodass sie nur einmal überprüft werden muss, anstatt jedes Mal indirekt neu getestet zu werden, wenn sich eine verwendende Komponente ändert.
use-Präfix – erfordert ein echtes Verständnis der zugrundeliegenden Muster von React. Teams, die sicherstellen wollen, dass dies von Anfang an richtig umgesetzt wird, suchen manchmal außerhalb ihres eigenen Personals nach spezialisierten ReactJS-Entwicklern, deren Erfahrung dazu beiträgt, dass das Hook-Design auch bei Projektexpansion stabil bleibt.Häufige Fehler, die vermieden werden sollten
Auch Hooks, die mit guten Absichten geschrieben werden, können auf einige vorhersehbare Weise fehlschlagen.
- Verletzung der Regeln für Hooks: Das Aufrufen eines Hooks innerhalb einer Bedingung, in einer Schleife oder aus einer gewöhnlichen Funktion anstelle eines Components oder eines anderen Hooks stört die Fähigkeit von React, den Zustand bei jeder Neuzeichnung konsistent zu halten. Das Ergebnis ist in der Regel ein seltsamer, intermittenter Fehler, dessen Ursache schwer nachzuvollziehen ist.
- Zu viele Aufgaben in einem Hook: Das Hineinpacken von Formvalidierung, Netzwerkanfragen und UI-Zustandsverwaltung in einen einzigen benutzerdefinierten Hook macht diesen Hook schwieriger zu testen, wiederverwendbarer und verständlicher als dann, wenn dieselben Aufgaben auf zwei oder drei kleinere, gezieltere Hooks verteilt wären.
useState verdient es, zu einem eigenen Hook zu werden. Wenn ein Teil der Logik nur an einer Stelle verwendet wird, führt seine Extraktion lediglich zu einer zusätzlichen Ebene der Indirektheit ohne wirklichen Nutzen.Fazit
Custom Hooks in React dienen nicht nur dazu, das Wiederholen von Code zu vermeiden, sondern fungieren auch als echtes Mittel, um eine sich ausdehnende Codebasis kohärent und einheitlich zu halten. Sobald ein Team lernt, logische Strukturen zu erkennen, die extrahiert werden sollten, neigen die Komponenten dazu, an Komplexität abzunehmen, Fehler werden leichter aufzuspüren, und das Verhalten bleibt im gesamten Programm konstant, anstatt sich allmählich zwischen Komponenten zu unterscheiden, die eigentlich auf dieselbe Weise funktionieren sollten. Da React-Anwendungen weiterhin an Umfang und Komplexität gewinnen, wird das Verständnis dafür, wann und wie man solide Custom Hooks entwickelt, zu einer grundlegenden Fähigkeit – anstatt etwas zu sein, das nur fortgeschrittenen Entwicklern vorbehalten ist.
Falls Ihr Team mit einer Codebasis zu kämpfen hat, die voller doppelter Logik ist, und echte Struktur hineinbringen möchte, könnte es sinnvoll sein, sich an eine React js Entwicklungsfirma zu wenden, die bereits ähnliche Refaktorisierungen bei anderen großangelegten Projekten durchgeführt hat.
Verwandte Artikel
- Typing React Hooks: useState, useEffect, useReducer und Custom Hooks – Erfahren Sie, wie man useState, useEffect, useReducer sowie Custom Hooks in TypeScript korrekt typisiert und wann sich die Verwendung von TypeScript gegenüber reinem JavaScript tatsächlich lohnt.